AWS API Gateway

By Vishvesh Patel · DevOps EngineerUpdated September 16, 2026

Choosing and running API Gateway. HTTP vs REST vs WebSocket and the 70% price difference, stages, throttling, custom domains and cost at scale.

Amazon API Gateway

API Gateway sits in front of your backend and handles the things every API needs: routing, authentication, throttling, request validation, TLS, and logging.

The first decision matters more than anything else on this page, and it is not the one people expect: there are three different products called API Gateway, with different features, different APIs and a substantial price difference.

HTTP, REST or WebSocket

HTTP APIREST APIWebSocket API
Price per million~$1.00~$3.50~$1.00
LatencyLowerHigher()
JWT authorizer built inYesNo (needs Lambda)No
Request validationNoYesNo
Mapping templatesNoYesYes
API keys and usage plansNoYesNo
WAF integrationNoYesNo
Private endpointsNoYesNo
CachingNoYesNo

Start with HTTP API. It is roughly 70% cheaper, measurably faster, and simpler to configure. For a typical Lambda- or container-backed JSON API it does everything needed, and its built-in JWT authorizer means Cognito or Auth0 integration without writing a custom authorizer.

Move to REST API only for a specific feature: API keys and usage plans for third-party consumers, request validation at the gateway, WAF, private endpoints inside a VPC, or response caching. Those are real reasons, but pick them deliberately rather than by default, because "REST" sounds like the standard choice and is the expensive one.

WebSocket APIs are for persistent bidirectional connections. Chat, live dashboards, notifications.

Creating an HTTP API

aws apigatewayv2 create-api \
  --name orders-api --protocol-type HTTP \
  --target "arn:aws:lambda:eu-west-1:123456789012:function:orders"

That single command creates the API, a default route, a Lambda proxy integration and an auto-deploying default stage. For anything beyond a prototype, be explicit:

API_ID=$(aws apigatewayv2 create-api --name orders-api --protocol-type HTTP \
  --cors-configuration 'AllowOrigins=https://app.example.com,AllowMethods=GET,POST,OPTIONS,AllowHeaders=content-type,authorization,MaxAge=300' \
  --query ApiId --output text)

INT_ID=$(aws apigatewayv2 create-integration --api-id "$API_ID" \
  --integration-type AWS_PROXY --payload-format-version 2.0 \
  --integration-uri "arn:aws:lambda:eu-west-1:123456789012:function:orders" \
  --query IntegrationId --output text)

aws apigatewayv2 create-route --api-id "$API_ID" \
  --route-key 'GET /orders/{id}' --target "integrations/$INT_ID"

CORS on an HTTP API is configuration, not code. Set it here and the gateway answers preflight requests itself. On a REST API you configure a mock OPTIONS method instead, which is one of the genuine ergonomic differences.

Stages

A stage is a deployed snapshot with its own URL, throttle limits, logging and variables:

aws apigatewayv2 create-stage --api-id "$API_ID" --stage-name prod \
  --auto-deploy \
  --default-route-settings 'ThrottlingBurstLimit=200,ThrottlingRateLimit=100,DetailedMetricsEnabled=true'

--auto-deploy publishes changes immediately. Convenient in development and usually wrong in production, where you want a deliberate deployment step.

REST APIs differ here in a way that catches people constantly: changes do nothing until you create a deployment.

aws apigateway create-deployment --rest-api-id "$REST_ID" --stage-name prod

Editing a REST API and wondering why the behaviour has not changed is almost always a missing deployment.

Stage variables let one configuration serve several environments:

aws apigatewayv2 update-stage --api-id "$API_ID" --stage-name prod \
  --stage-variables 'lambdaAlias=prod'

Throttling and quotas

Two different mechanisms, frequently conflated.

Throttling is rate limiting, applied per stage or per route, and it protects your backend:

aws apigatewayv2 update-stage --api-id "$API_ID" --stage-name prod \
  --route-settings '{"GET /orders/{id}": {"ThrottlingRateLimit": 50, "ThrottlingBurstLimit": 100}}'

Rate limit is steady-state requests per second; burst limit is the token bucket depth for spikes. Exceeding either returns 429 Too Many Requests, and the account-level default of 10,000 requests per second across all APIs in a region is worth knowing before a launch.

Usage plans and API keys are quotas per consumer, requests per day or month, and they are REST API only. If you need to give partners individual keys with monthly limits, that alone justifies REST API.

aws apigateway create-usage-plan --name partner-tier \
  --throttle 'rateLimit=10,burstLimit=20' \
  --quota 'limit=10000,period=MONTH'

An important caveat: API keys identify a caller for metering; they are not authentication. Anyone with the key has whatever access the API grants. Use an authorizer for identity.

Custom domains

aws apigatewayv2 create-domain-name --domain-name api.example.com \
  --domain-name-configurations 'CertificateArn=arn:aws:acm:eu-west-1:…,EndpointType=REGIONAL,SecurityPolicy=TLS_1_2'

aws apigatewayv2 create-api-mapping --domain-name api.example.com \
  --api-id "$API_ID" --stage prod --api-mapping-key v1

The certificate region differs from CloudFront: a regional endpoint needs the certificate in the same region as the API, while an edge-optimised endpoint needs it in us-east-1. Getting this backwards is a common first-time error.

API mappings are what remove the stage name from your URLs, so consumers call api.example.com/v1/orders rather than the default abc123.execute-api.eu-west-1.amazonaws.com/prod/orders.

Logging

Metrics are on by default; access logs are not, and they are what you will want during an incident:

aws apigatewayv2 update-stage --api-id "$API_ID" --stage-name prod \
  --access-log-settings 'DestinationArn=arn:aws:logs:eu-west-1:123456789012:log-group:/aws/apigw/orders,Format={"requestId":"$context.requestId","ip":"$context.identity.sourceIp","route":"$context.routeKey","status":"$context.status","integrationStatus":"$context.integrationStatus","integrationError":"$context.integrationErrorMessage","latency":"$context.responseLatency"}'

$context.integrationErrorMessage is the field worth including above all others. When the gateway returns a 502, that is where the actual reason appears.

$context.responseLatency versus $context.integrationLatency separates gateway overhead from backend time, which settles most "the API is slow" arguments.

API Gateway or an ALB

A reasonable question, since both can front a service:

Use API Gateway whenUse an ALB when
Backend is LambdaBackend is containers or EC2
You need per-consumer keys and quotasTraffic is high and steady
Request validation or transformationYou want predictable hourly cost
Usage is spiky or low

The deciding factor at scale is usually cost shape: API Gateway charges per request with no hourly fee, while an ALB charges by the hour plus capacity units. Low or spiky traffic favours API Gateway; sustained high volume favours an ALB, and the crossover arrives sooner than most people expect.

Common errors

{"message":"Internal server error"}

A 502 from a Lambda integration, almost always a malformed response shape. See API Gateway and Lambda. Check integrationErrorMessage in the access log.

{"message":"Missing Authentication Token"}

Misleading: it usually means the path does not match any route, not an auth problem. Check the route key and whether the stage is in the URL.

{"message":"Too Many Requests"}

A 429 from stage, route or account-level throttling.

REST API changes have no effect. No deployment was created.

Quick reference

TaskCommand
Create an HTTP APIaws apigatewayv2 create-api --protocol-type HTTP
Add a routeaws apigatewayv2 create-route --route-key 'GET /x'
Create a stageaws apigatewayv2 create-stage --auto-deploy
Deploy a REST APIaws apigateway create-deployment --stage-name prod
Set throttlesupdate-stage --default-route-settings 'ThrottlingRateLimit=…'
Custom domainaws apigatewayv2 create-domain-name
Map to a stageaws apigatewayv2 create-api-mapping --api-mapping-key v1
List APIsaws apigatewayv2 get-apis --query 'Items[].[Name,ApiId,ProtocolType]'

Key takeaways

  • Three products share the name. HTTP API is ~70% cheaper and the right default.
  • Choose REST API for a reason: API keys, request validation, WAF, private endpoints, caching.
  • REST API changes require create-deployment. HTTP APIs can auto-deploy.
  • CORS is configuration on an HTTP API and a mock OPTIONS method on a REST API.
  • Throttling protects your backend; usage plans meter consumers, and only REST has the latter.
  • API keys are not authentication.
  • Certificate region depends on endpoint type: regional matches the API, edge-optimised is us-east-1.
  • Turn on access logs with integrationErrorMessage before you need to debug a 502.

Check your understanding

Exercise

Changes that never take effect

A team edits a REST API's integration in the console, saves successfully, and the deployed endpoint keeps behaving as before. No errors appear anywhere. What is missing?

Exercise

Choosing between HTTP and REST APIs

A new JSON API is backed by Lambda, authenticates with Cognito JWTs, and must issue individual keys to partners with monthly request quotas. Which API type fits?


Frequently Asked Questions

What is the difference between HTTP API and REST API in API Gateway?

They are separate products with separate APIs. HTTP API is newer, roughly 70% cheaper per request, lower latency, and includes a built-in JWT authorizer, which covers most Lambda- or container-backed JSON APIs. REST API is older and more featureful: API keys and usage plans, request validation at the gateway, WAF integration, private VPC endpoints, response caching and mapping templates. Start with HTTP API and choose REST when you specifically need one of those, rather than because "REST" sounds like the default.

Why do my API Gateway changes not take effect?

On a REST API, because configuration and what is serving traffic are separate: a stage continues serving the last deployment until you run create-deployment for it. Nothing errors, so the change simply appears to be ignored. HTTP APIs avoid this when the stage is created with --auto-deploy. If you are moving between the two types, this is the difference that bites first.

What does "Missing Authentication Token" mean?

Usually that the request path does not match any configured route, despite the message pointing at authentication. API Gateway returns it for an unmatched path on a REST API, so the likely causes are a typo in the path, a missing stage name in the URL (/prod/orders rather than /orders on a default endpoint), or a method that is not configured on an otherwise valid resource. Check the route or resource definition before investigating authorizers.

How does API Gateway throttling work?

Two levels, which are easy to conflate. Stage and route throttling limit requests per second with a burst allowance, protecting your backend. Exceeding either returns 429. Usage plans, available only on REST APIs, meter individual consumers by API key with daily or monthly quotas. There is also an account-level default of 10,000 requests per second across all APIs in a region, which is worth raising before a launch rather than during one.

Should I use API Gateway or an Application Load Balancer?

API Gateway when the backend is Lambda, when you need per-consumer keys and quotas, request validation or transformation, or when traffic is low and spiky. It charges per request with no hourly fee. An ALB when the backend is containers or EC2 and traffic is high and steady, since its hourly plus capacity pricing is cheaper at sustained volume. The crossover point arrives sooner than most people expect, so it is worth modelling if you are anywhere near it.

Do API keys secure my API?

No. An API key identifies a caller so you can meter and throttle them; it is not authentication and should not be treated as a secret that grants access. Anyone holding the key has whatever access the API allows. Use a JWT authorizer, IAM authorisation, or a Lambda authorizer for identity and permissions, and use API keys alongside them purely for usage plans and quotas.

Continue Learning

Explore Related Topics

When it breaks

Related Resources