Choice 19. By Nicolas Dao

Function URL or API Gateway?

My Lambda needs an HTTPS endpoint. When is a function URL enough, and when do I start on API Gateway from day one?

A function URL by default: free, up to 15 minutes, nothing to keep in sync. API Gateway from day one when you sell an API, need a private one, or need what only it does at the door. Often both: the partner API on API Gateway, the app's own endpoints on function URLs, the same code behind them.

When to pick which

Pick a function URL when

  • It's your own app's API, or service-to-service calls signed with IAM.
  • Requests can take longer than 30 seconds: reports, LLM calls, file processing. A function URL waits up to 15 minutes.
  • You stream from Node.js outside a VPC, up to 200 MB per response.
  • A webhook from one provider, whose signature you check in code.

Pick API Gateway when

  • You sell or meter an API for third parties: per-customer keys, quotas and throttling tiers (REST API).
  • Bad requests must be rejected before your code runs, against a published contract (REST API validation).
  • The API must not be public: callers inside a VPC or on premises (REST private API).
  • No Lambda in the path: a webhook straight into SQS, EventBridge or Step Functions (HTTP API).
  • JWT checks at the door, routes over many functions under one domain, client certificates (mTLS), caching or canary releases.

Both, when

  • The partner API on API Gateway, with keys, quotas and validation; the app's own endpoints on function URLs. The same code behind both.
  • Then lock the function URL behind the partner API down (IAM auth, or no URL at all): a public URL with auth NONE bypasses everything API Gateway enforces.

Questions that change the answer

  • Will anyone outside your team call this API, and will you bill or limit them per customer? That's API Gateway's REST API.

  • Can any request take longer than 30 seconds? An HTTP API stops at 30, a REST API at 29 by default.

  • Must the API stay off the public internet? Function URLs are public only.

  • Does the domain matter to clients? Put it on a Worker or CloudFront from the first deploy, so a later move is an origin change, not a new URL.

The short version

Function URL HTTP API REST API
Price on top of Lambda (Sydney) $0 $1.29 per million requests $3.50 per million
At 100M requests a month $0 $129 $350
Longest request 15 minutes 30 seconds, fixed 29 seconds by default, more on request for regional and private APIs
Streaming Yes, up to 200 MB (not inside a VPC) No Yes, since November 2025, in its own format
Event format Payload 2.0 Payload 2.0: same handler 1.0: needs an adapter
Custom domain No: a Worker or CloudFront in front Yes Yes
Auth at the door IAM or none IAM, JWT, Lambda authorizer IAM, Cognito, Lambda authorizer, API keys
Per-customer keys, quotas, throttling No: reserved concurrency limits everyone together No Yes
Request validation No No Yes
WAF No: in front No: in front Attached directly
Private API (VPC only) No: public only No Yes
Straight into SQS, EventBridge, Step Functions No: your function always runs Yes, a fixed list Yes, any AWS service
Caching No No Yes

Price doesn't decide this one. At 100 million requests a month the dearest door costs $350, small next to what such a product spends on compute and people. Features and limits decide it.

Why a function URL is my default

Most APIs I build are the app's own: a front end and its backend, or one service calling another. For those, everything API Gateway adds is configuration to keep in sync with the code (routes, stages, deployments, integrations) for features nobody uses. A function URL is one HTTPS endpoint on one function, created with it in Pulumi, and it waits up to 15 minutes where API Gateway stops at about 30 seconds.

What it doesn't have is the edge: no custom domain, no WAF, no caching, no per-client rate limit. Its only throttle is reserved concurrency, which returns 429 above the limit for everyone at once. So anything public gets a door in front: a Cloudflare Worker (domain, rate limits, bot rules, streaming passes through), or CloudFront when everything must stay on AWS.

When I start on API Gateway from day one

  • You sell the API. Partners get their own keys, quotas and throttling tiers, maybe a developer portal. That's the REST API's usage plans, and a function URL has nothing like them.
  • The contract is enforced at the door. Request validation against a schema, so bad payloads never reach your code. REST only.
  • The API must stay private. Callers in a VPC, or on premises over Direct Connect. A function URL is reachable from the public internet only; a REST private API isn't.
  • There's no code to run. A webhook that goes straight into a queue or a workflow: an HTTP API integrates with SQS, EventBridge, Kinesis and Step Functions directly, so you don't own a function that only forwards.
  • The door does real work. JWT checks off the function (HTTP API), many routes over many functions under one domain, client certificates for B2B (mTLS), caching, canary releases (REST).

WebSockets are the exception: API Gateway has a WebSocket API, but for live shared state I use a Durable Object instead (the live auction shows why).

Switching later

To an HTTP API, the handler doesn't change. Both send payload 2.0. What changes is around it: the 30-second ceiling, no streaming, and the CORS settings that move from the URL to the API (set them in one place, or browsers get two Access-Control-Allow-Origin headers).

To a REST API, it does. A REST API sends the older 1.0 event (httpMethod, multiValueHeaders, no cookies field) and expects a 1.0 response, so the handler needs a thin adapter, or two small entry points around the same logic. Streaming changes format too.

Keep the address stable from day one. A function URL's own address is a long lambda-url hostname. If clients ever call it directly, moving is a breaking change. Put the domain on a Worker or on CloudFront from the first deploy, and the move to API Gateway, or to Lambda Web Functions when they reach your region, is one origin change that clients never see.

One trap with CloudFront in front: with origin access control on the function URL, every POST and PUT must carry a SHA-256 hash of its body in a header, because Lambda doesn't accept unsigned payloads that way. Browsers and partners won't send it. Either use a Worker, or leave the URL's auth at none and check a secret header that only CloudFront adds.

Lambda Web Functions, a third option to watch

Launched on 12 October 2026 and not in Sydney yet: a Node.js web server (Express, Hono) on Lambda with its own HTTPS endpoint, many requests per environment, streaming, 15 minutes per request and a per-endpoint rate limit. No custom domain or WAF of its own either, so the same door goes in front. For an app's own API it could replace the function URL once it reaches your region; it doesn't replace API Gateway's keys, quotas and validation. Lambda, Web Functions or Workers? compares them.

Sources, checked on 25 October 2026: function URLs or API Gateway (AWS), function URL configuration and throttling, payload format 1.0 and 2.0, REST API response streaming, REST and HTTP APIs compared, API Gateway quotas, API Gateway pricing, CloudFront origin access control for function URLs, Lambda Web Functions launch.

More choices

  1. 01 Lambda, Web Functions or Workers? Where should this piece of logic run?
  2. 02 Lambda, Fargate or EC2? My Lambda is busy all day, or its reserved concurrency keeps going up. When is it time to move to a container, and where is the line?
  3. 03 SQS, EventBridge or SNS? Something happens in my app and other code must act on it. Do I put it in a queue, on an event bus, or on a topic?
  4. 04 SQS retries or Durable Functions? A job calls something flaky (a third-party API, an LLM, a slow Postgres). How do I retry it reliably, and when do I reach for Lambda durable functions instead of tuning SQS?
  5. 05 pgvector or S3 Vectors? Where should my embeddings live?
  6. 06 Pulumi or Terraform? We're putting our infrastructure in code. Pulumi or Terraform, and what if we already run one of them?
  7. 07 Cloudflare or S3 and CloudFront for a website? Where should a website, SPA or PWA live, Cloudflare static hosting or S3 behind CloudFront, and where do its heavy files go?
  8. 08 CloudWatch and Firehose, side by side How do I keep chatty logs without a CloudWatch-sized bill?
  9. 09 Athena or DuckDB? How should I query my data lake, and what changed when AWS bought DuckDB's company?
  10. 10 Neon or Aurora? I need Postgres for an app on AWS. When is Neon the right call, and when does it have to be Aurora?
  11. 11 Better Auth or Cognito? Which sign-in should my app use, and what do I actually get for free?
  12. 12 Why I ended up on AWS Which cloud should my company run on, and is AWS just the one you know?
  13. 13 Better Auth, run yourself or managed by Neon? My app is on Neon. Should I run Better Auth myself, or switch on Neon Auth, which is Better Auth managed by Neon?
  14. 14 Stripe or PayPal Should we take payments with Stripe or PayPal, and when is PayPal worth the pain?
  15. 15 Tailscale or Cloudflare Tunnel? I need to reach a private box or VPC, or put a service from it online. Is that Tailscale or Cloudflare Tunnel?
  16. 16 Resend or SES? Our app sends email, and maybe a newsletter. Resend, or Amazon SES in our own AWS account?
  17. 17 WhatsApp or Telegram Our bot should reach users in a messaging app. WhatsApp or Telegram, and why did yours get blocked?
  18. 18 Which model, at what price Claude, GPT or an open model? Which is the cheapest model that's good enough, tier by tier?

Want this stack in your AWS account?

Cloudless Labs is a Sydney consultancy. We migrate on-premises systems to AWS, build serverless apps on this stack, and coach teams to ship with Claude Code and Codex.

Contact Us

For general inquiries, please contact us at:

For e-learning capabilities, please contact: