Module 12 · Microservices patterns · Lesson 2 of 8
API gateway
One front door for many services: routing, authentication, rate limiting, TLS, and protocol translation in a single edge layer. What belongs in the gateway and what does not, the aggregation temptation.
Why it matters
Clients should not need to know that orders, users and payments are twelve services on different hosts, each with its own authentication and rate limits. An API gateway gives them one address, one security model and one place where cross-cutting edge policy lives. It is also a common place to accumulate business logic until it becomes the new monolith, or to create a bottleneck that every request depends on. The design skill is knowing which responsibilities belong at the edge.
The idea
An API gateway is a reverse proxy at the edge that receives all external requests, applies cross-cutting policy and routes each request to the right internal service. It is the microservices-era descendant of the reverse proxy from the Networking module, with awareness of services, identities and APIs.
What belongs in the gateway
- 1
Routing
Path, host or header based routing to services, with versions (/v1, /v2) and canary weights. - 2
Authentication and coarse authorization
Validate tokens (JWT signature, expiry, audience), reject anonymous requests to protected routes, attach the verified principal as headers for services. Fine-grained authorization stays in services, next to the data. - 3
Rate limiting and quotas
Per API key, per user, per IP, with 429 and Retry-After, from the API module. - 4
TLS termination and security headers
One place for certificates, HTTP to HTTPS redirects, CORS, request size limits and basic input filtering. - 5
Protocol translation
HTTP and JSON outside, gRPC inside; WebSocket upgrade handling; HTTP/2 or HTTP/3 to clients regardless of what services speak. - 6
Observability
Request logging, correlation id injection, metrics per route, the first span of every trace. - 7
Resilience at the edge
Timeouts, retries for idempotent routes, circuit breakers per upstream, load shedding under overload.
What does not belong
Business logic: a gateway that validates order contents or computes prices is a monolith in a proxy's clothing, owned by nobody and deployed by everybody. Heavy aggregation: composing a screen from six services in the gateway makes it a bottleneck and couples it to every API change; the Backend for frontend pattern, next lesson, is the structured answer. Data transformation beyond simple header and format mapping. If the gateway's config needs a release when a service changes its payload, something leaked.
Keeping it from becoming the bottleneck
Every request crosses the gateway, so it must be stateless (policy and config loaded from a store, no per-session memory), horizontally scaled behind a layer-4 balancer or anycast, and deployed independently of services. Use a proxy built for it (Envoy, NGINX, HAProxy, Kong, Traefik, cloud API gateways) rather than hand-written code. Externalise rate-limit counters to a shared store. Make configuration declarative and versioned so a bad routing change rolls back in seconds. Watch its latency overhead, typically one to a few milliseconds.
One gateway or several
Large systems run several: a public gateway for third parties with strict quotas and documentation, an internal or partner gateway, and sometimes one per client type (the BFF pattern). The guiding rule is that a gateway should have one audience with one policy set; mixing audiences means the most restrictive policy constrains everyone or the laxest one leaks.
| Gateway | Load balancer | Service mesh | |
|---|---|---|---|
| Position | Edge, north-south traffic | In front of any tier | Between services, east-west traffic |
| Knows about | APIs, routes, identities, quotas | Backends and health | Service identities, mTLS, retries, traffic policy |
| Typical products | Kong, Envoy Gateway, AWS API Gateway, Apigee | ALB, NGINX, HAProxy | Istio, Linkerd, Consul Connect |
| Replaces the others? | No; often sits on top of a balancer and in front of a mesh | No | No; handles internal traffic the gateway never sees |