skip to content

What is an AWS Lambda function URL, and when would you use one instead of putting API Gateway in front of the function?

level: middleimportance: nice to knowfreq 36%

answer

  1. Lambda hosts the endpoint itself
  2. two auth types, and only two
  3. one URL, exactly one function
  4. the gateway's features become your code
  5. the only HTTP path that streams

basics

~20 s

A function URL is a built-in HTTPS endpoint on a single Lambda function, created with an auth type of NONE or AWS_IAM. It invokes the function synchronously with no extra service in the path. Choose it for simple single-function endpoints, webhooks and streamed responses.

solid answer

~50 s

A function URL is a dedicated `https://<url-id>.lambda-url.<region>.on.aws` endpoint that Lambda itself hosts for one function or alias. You create it with `CreateFunctionUrlConfig`, choosing `AuthType` of `AWS_IAM` — callers must sign requests and hold `lambda:InvokeFunctionUrl` — or `NONE`, which makes it publicly reachable with authorization left to your handler. It always invokes synchronously and delivers an event in the same payload format as an API Gateway HTTP API, and it has built-in CORS configuration. What it does not give you is everything API Gateway exists for: routing across many functions, request validation, usage plans and API keys, custom authorizers, custom domains, or a WAF attachment. So a function URL suits a single-purpose endpoint — a webhook receiver, an internal service, a demo — and it is the only way to expose response streaming over HTTP. Anything that is an actual API with several routes and managed access belongs behind API Gateway.

code

bash · 4 lines
bash
aws lambda create-function-url-config \
  --function-name my-function \
  --auth-type AWS_IAM \
  --invoke-mode RESPONSE_STREAM

go deeper

for a junior

Recall that a function URL is a built-in HTTPS endpoint for one Lambda function, always synchronous, with an auth type of either AWS_IAM or NONE.

for a middle

Be able to list what API Gateway provides that a function URL does not — routing, authorizers, usage plans, request validation, custom domains — and note the payload format is the same as an HTTP API.

for a senior

Show the operational angle: AuthType NONE moves authorization into handler code you now own, unvalidated requests become billed invocations, and WAF requires fronting the URL with CloudFront.

for a principal

Frame it as a boundary decision — how much API-management responsibility you are willing to hold in application code versus a managed edge, and whether a fleet of function URLs is governable across teams.

## What it is Before function URLs existed, exposing a Lambda function over HTTP always meant putting another service in front of it. A function URL removes that: Lambda gives the function its own HTTPS endpoint on the `lambda-url` domain, and requests to it are turned into synchronous invocations. You create one against a function or a specific alias: ```bash aws lambda create-function-url-config \ --function-name my-function \ --auth-type AWS_IAM ``` A URL is bound to one function (optionally qualified by an alias), and it is always synchronous — there is no way to make an HTTP request to a function URL result in an asynchronous invocation. ## The two auth types, and what they really mean `AuthType` takes exactly two values. **`AWS_IAM`** requires the caller to sign the request with SigV4 and hold the `lambda:InvokeFunctionUrl` permission. Note that this is a distinct action from `lambda:InvokeFunction` — a policy that grants only the latter does not open the URL. This is a good fit for service-to-service calls inside an account or organisation, and for anything a signed SDK client will reach. **`NONE`** makes the endpoint publicly invokable by anyone who knows the URL. Lambda still requires a resource-based policy statement permitting public invoke, so it is an explicit act rather than an accident, but from that point on **all** authentication and authorization is your handler's job: verifying a webhook signature, checking a bearer token, whatever the caller uses. The URL's obscurity is not a security control. ## The event your handler receives A function URL delivers the request in the same payload format version 2.0 that an API Gateway HTTP API uses: method, raw path, query string, headers, and the body (base64-encoded when binary). The handler responds with a status code, headers and a body, or with a bare object that Lambda wraps as a 200 JSON response. Practically, this means a handler written for an HTTP API usually works unchanged behind a function URL — the migration cost between them is low, which is a reasonable argument for starting with the simpler one. CORS is configured on the URL itself rather than in your code: allowed origins, methods, headers, credentials and max age, with preflight handled for you. ## Response streaming A function URL's `InvokeMode` is `BUFFERED` by default, meaning Lambda collects the entire response and returns it in one piece. Setting it to `RESPONSE_STREAM` lets the function send bytes as it produces them, which matters for two cases: time-to-first-byte on a slow generation (an LLM-style token stream, a report assembled from several calls), and payloads larger than the buffered response limit of 6 MB. Streaming is available through function URLs and the `InvokeWithResponseStream` API — not through an API Gateway integration — so if you need streaming over HTTP, the function URL is not merely simpler, it is the mechanism. ## What you give up Everything API Gateway is for: - **Routing.** One URL, one function. There is no path-to-function mapping; the full path arrives inside the event and your handler routes it, or you deploy one function per endpoint. - **Access management.** No usage plans, no API keys, no per-client quotas. - **Custom authorizers.** No Lambda authorizer or JWT authorizer stage; token validation is handler code. - **Request validation and transformation.** Nothing rejects a malformed body before it reaches you — and you pay for that invocation. - **Custom domains.** The endpoint lives on the `on.aws` domain. - **WAF.** You cannot attach a web ACL to a function URL directly; the usual pattern is to put CloudFront in front of it, which also buys you a custom domain and caching. ## Choosing Reach for a function URL when the thing you are exposing is genuinely one function with one job: a webhook endpoint for a third-party provider, an internal callback, a small tool, a prototype, or anything that needs streamed responses. Reach for API Gateway when you are building an API — several routes, third-party consumers who need keys and quotas, request validation, a branded domain, or managed authorization. The decision is about how much of an API gateway's job you would otherwise be writing inside your handler.

  • What does setting a function URL's InvokeMode to RESPONSE_STREAM change?
    The function sends response bytes as it produces them instead of Lambda buffering the whole payload first. That improves time-to-first-byte for slow generation and lifts you past the 6 MB buffered-response limit. It is available through function URLs and InvokeWithResponseStream, and not through an API Gateway integration.
  • With AuthType NONE, what protects the endpoint?
    Only what your handler does. Lambda still requires an explicit resource-based policy allowing public invoke, so exposure is deliberate, but from there authentication is entirely application code — webhook signature verification, bearer token checks, rate limiting. The URL being unguessable is not a control; treat the endpoint as fully public.
  • Can you attach AWS WAF to a Lambda function URL?
    Not directly. The standard pattern is to put a CloudFront distribution in front of the function URL and attach the web ACL there, which also gives you a custom domain, TLS on your own certificate, and optional caching. If you need managed protections at the edge, that hop is the price of using a function URL.

saying these in an interview costs you the question

  • Thinks a function URL can route several paths to different functions
  • Assumes AuthType NONE is safe because the URL is unguessable
  • Believes lambda:InvokeFunction is enough to call a function URL
  • Claims response streaming works through API Gateway integrations
  • Expects usage plans or API keys on a function URL

context