Skip to content

Amazon API Gateway

Amazon API Gateway is a managed service for creating, publishing, monitoring and securing REST, HTTP and WebSocket APIs. It handles TLS termination, authorisation, request routing, throttling and logging, so a backend can be a bare Lambda function, an internal service behind a load balancer, or an AWS service called directly.

Most of the guidance written about API Gateway before 2020 describes REST APIs only. There are three types, and the choice is not cosmetic — it decides both the price and the feature set.

REST APIHTTP APIWebSocket API
ProtocolRequest/response over HTTPSRequest/response over HTTPSStateful, full-duplex
Relative costHighestLowerPer message and per connection-minute
Typical usePublic or monetised APIs needing API keys, request validation, WAF or private endpointsLambda and HTTP proxying where none of those are neededChat, live dashboards, streaming updates

REST APIs support the larger feature set. HTTP APIs are deliberately minimal so they can be offered at a lower price, and for a straightforward Lambda proxy they are usually the right default. WebSocket APIs are a different shape entirely: the client holds a connection open and API Gateway routes incoming messages to backend integrations by message content.

Features that exist only on REST APIs include response caching, API keys and usage plans, per-client rate limiting, request validation, request-body mapping templates, custom gateway responses, canary release deployments, mock integrations, execution logging, X-Ray tracing, AWS WAF integration, resource policies and private endpoints. HTTP APIs, in exchange, offer automatic deployments, native JWT authorizers and private integrations with AWS Cloud Map.

AWS maintains a feature-by-feature comparison in Choose between REST APIs and HTTP APIs; check it before committing, because the list moves.

A REST API is published to one of three endpoint types.

Regional. The API is served from the Region it is deployed in. This is the default and the right choice when clients are in the same Region, or when a CDN is already being managed separately in front of the API.

Edge-optimised. API Gateway fronts the API with a CloudFront distribution, so requests enter the AWS network at the nearest edge location. This helps geographically dispersed clients; it does not cache responses unless caching is configured.

Private. The API is reachable only from inside a VPC through an interface VPC endpoint. Nothing about it is exposed to the internet.

HTTP APIs are Regional only. Private endpoints and edge optimisation are REST-only.

The integration is what API Gateway calls when a route matches:

  • Lambda — proxy integration passes the whole request through and takes the function’s response as-is; non-proxy integration uses mapping templates to reshape both.
  • HTTP — any reachable HTTP endpoint, public or private.
  • AWS service — call another AWS service directly (for example putting a record on a Kinesis stream or a message on an SQS queue) with no compute in between.
  • Private — a Network Load Balancer, Application Load Balancer, or, for HTTP APIs, an AWS Cloud Map service.
  • Mock — return a canned response without a backend; useful for CORS pre-flight and for stubbing a contract before the backend exists. REST APIs only.

A REST API can transform requests and responses with Velocity mapping templates: rewrite the body, move values between headers, query string and path, and convert content types. It can also validate the request against a JSON Schema model and reject malformed input before the backend is invoked.

HTTP APIs support parameter mapping (headers, path and query string) but not body transformation and not request validation. Where an HTTP API is chosen, validation belongs in the backend.

A REST API is not live until a deployment is made to a stage. Stages carry their own throttle settings, logging configuration, cache configuration and stage variables, which is how a single API definition serves dev, test and prod. Canary release deployments — sending a fixed percentage of stage traffic to a new deployment — are a REST API feature; HTTP APIs instead support automatic deployment on change.

Response caching is a REST API feature, configured per stage with a provisioned cache size and a per-method time-to-live. When a cached entry is present, API Gateway answers directly and the backend is never invoked, which reduces both latency and backend cost. Cache keys can be built from selected request parameters, and clients can be permitted to bypass the cache with a header if the API grants them that right. HTTP APIs have no built-in cache; put CloudFront in front of them instead.

  • IAM — SigV4-signed requests, for callers that already hold AWS credentials.
  • Amazon Cognito user pools — token validation against a user pool.
  • Lambda authorizers — arbitrary token or request-parameter validation in a function, with a cacheable policy result.
  • JWT authorizers — native OIDC/OAuth 2.0 token validation. HTTP APIs only.
  • Resource policies — allow or deny by source VPC, VPC endpoint or account. REST only.
  • Mutual TLS — client-certificate authentication on a custom domain, on both types.

API keys identify a caller; they are not an authentication mechanism and should never be the only thing between the internet and the backend.

Throttling is applied at several levels, and a request is rejected by the first one it exceeds:

  1. Account level, per Region, across all APIs.
  2. Stage and method level, set on the deployment.
  3. Usage plan level, per API key, when the API is a REST API with usage plans configured.

API Gateway throttles with a token bucket: a steady refill rate plus a burst allowance, so a short spike above the rate limit is absorbed while a sustained one is not. A request that is throttled is rejected with HTTP 429 Too Many Requests and the body {"message": "Too Many Requests"}. Usage plans additionally impose a quota — a hard cap on requests per day, week or month for a given API key — and a request that exceeds the quota is also rejected with 429.

Usage plans and per-client rate limiting are REST-only. An HTTP API can be throttled at the account, stage and route level, but there is no per-client dimension.

429 means the caller should slow down and retry, not that the request was invalid. A client that retries immediately makes the problem worse; a client that retries in lockstep with every other client produces a thundering herd. Two rules cover it:

  • Honour a Retry-After header when the server sends one.
  • Otherwise back off exponentially with jitter, and give up after a bounded number of attempts.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function callApi(url, { attempts = 5 } = {}) {
for (let attempt = 0; attempt < attempts; attempt++) {
const response = await fetch(url);
if (response.status !== 429 && response.status !== 503) {
return response;
}
const retryAfter = Number(response.headers.get('Retry-After'));
const backoff = Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000
: Math.min(2 ** attempt * 100, 20_000) * (0.5 + Math.random());
await sleep(backoff);
}
throw new Error(`Still throttled after ${attempts} attempts`);
}

The AWS SDKs implement this behaviour already, with configurable retry modes; hand-rolled retry logic is only needed for direct HTTP callers.

The same four algorithms come up whenever a rate limit has to be designed rather than consumed:

  • Fixed window — simplest to implement, but allows a double-rate burst across a window boundary.
  • Sliding window — more accurate, and removes the boundary burst.
  • Token bucket — allows a controlled burst while holding a long-run average. This is what API Gateway uses.
  • Leaky bucket — smooths output to a constant rate, which suits queue-backed processing.

Example: a REST API over Lambda and DynamoDB

Section titled “Example: a REST API over Lambda and DynamoDB”

A minimal CRUD API has two routes and two functions:

  • GET /customer/{id} — API Gateway matches the route, invokes a getCustomer function, which reads the item from DynamoDB and returns it. With stage caching enabled, a repeated request for the same customer is answered from the cache and the function is never invoked.
  • PUT /customer/{id} — API Gateway validates the request against the method’s model, invokes a createCustomer function, which writes the item and returns a confirmation.

Everything above the function — TLS, authorisation, throttling, logging, retries on 5xx — is the gateway’s responsibility, and none of it is code in the handler.

An API is published under a generated hostname of the form {api-id}.execute-api.{region}.amazonaws.com. A custom domain name maps a real hostname onto one or more APIs and stages, using an ACM certificate and SNI. Both REST and HTTP APIs support custom domains, and a single domain can route different base paths to different APIs.

CloudWatch metrics (Count, 4XXError, 5XXError, Latency, IntegrationLatency, CacheHitCount, CacheMissCount) are available for both REST and HTTP APIs, and access logs can be delivered to CloudWatch Logs. Execution logging — the verbose per-request trace of what the gateway did internally — and X-Ray tracing are REST-only. Alarm on 5XXError and on Latency percentiles rather than averages.

Charges are per million requests, plus data transfer, plus an hourly charge for a provisioned cache. HTTP APIs cost materially less per request than REST APIs, so the API type is the single largest cost lever. After that: cache aggressively where responses are cacheable, and use usage-plan quotas to make third-party abuse bounded rather than unbounded.