API Gateway vs Reverse Proxy
The whole distinction is how deeply the box reads the request before it acts: a reverse proxy routes on the envelope — TLS SNI, the Host header, a path prefix — and then forwards the byte stream mostly untouched; an API gateway parses the application message — the HTTP method and route, JWT claims, sometimes the body — so it can authenticate, throttle per consumer, transform, and fan out to several services before it answers. Everything else (which one caches, which does load balancing) follows from that one difference in inspection depth.
The practical consequence that most comparisons miss: an API gateway is almost always built on top of a reverse proxy. Kong is NGINX plus a Lua policy layer; most managed gateways (and Istio's ingress) are Envoy plus filters. So this is rarely "A or B" — it is "a reverse proxy alone" versus "a reverse proxy plus an application-policy layer."
Worked example: one request, two levels of handling
A mobile client sends GET https://api.shop.com/v2/orders/8891 with header Authorization: Bearer eyJhbGci... over TLS 1.3. Here is what each box actually does with those exact bytes.
A plain reverse proxy (NGINX) does four things and stops
- Accept TCP on :443, read the TLS SNI = api.shop.com, pick the matching certificate, terminate TLS.
- Read the request line and
Host. Matchlocation /v2/against config → upstream poolorders_backend. - Pick a member by round-robin:
10.0.3.7:8080. - Stream the bytes upstream and the response back. Added latency ≈ 1–2 ms. It never parsed the Bearer token, never looked at
8891, never counted this consumer's requests.
An API gateway parses the message and runs a policy pipeline
| Stage | What it does | Data it reads | Result |
|---|---|---|---|
| 1. TLS / decode | Terminate TLS (often delegated to the edge proxy in front), decode HTTP | SNI, request bytes | plaintext request |
| 2. Route match | Match GET /v2/orders/{id} against the API spec | method + path template | route = getOrder |
| 3. AuthN | Verify JWT RS256 signature against cached JWKS, check exp | Authorization claims | sub=user_4471, valid |
| 4. AuthZ + rate limit | Token bucket for user_4471: 100 req/min, current count 63 | consumer id | allowed (37 left) |
| 5. Transform | Strip client's Authorization, inject trusted X-User-Id: 4471 | headers | rewritten request |
| 6. Route / aggregate | Call orders-svc; optionally join shipping-svc for the ETA | route + body | merged 200 payload |
| 7. Response | Add CORS headers, record per-route latency metric, return JSON | response body | 200 to client |
Added latency ≈ 8–15 ms (representative figures, not benchmarks). The gateway did real work that a reverse proxy, as deployed — config-driven routing with no policy engine — does not do; you can bolt that work onto NGINX with Lua, but at that point you have hand-built a gateway (see the first pitfall for why that usually goes badly). And you paid for every microsecond of it. Note stages 3–6 are exactly the "application-level policy layer" bolted on top of the same routing the reverse proxy already did in its four steps.
Where each stage lives in a real gateway
On Envoy-based gateways the pipeline is literally the HTTP filter chain: the TLS transport socket handles stage 1, route matching in the HTTP connection manager is stage 2, a jwt_authn filter is stage 3, ext_authz / ratelimit filters are stage 4, header mutation covers stage 5, the router filter selecting an upstream cluster is stage 6, and CORS and access-log handling run on the response path for stage 7 (filter names per Envoy's HTTP filter reference; exact names can drift across versions, so check the current docs). On Kong, stages 3–5 are Lua plugins hung off NGINX's access phase, with response-side work in the header_filter/body_filter phases. That is the concrete sense in which a gateway is a reverse proxy plus a policy layer: the proxy provides the chassis — connection handling, routing, streaming — and the gateway's stages are plugins bolted into that chassis's request lifecycle.
Stage 3 failure drill: the JWKS endpoint goes dark
The identity provider's JWKS endpoint is unreachable and the gateway's cached signing keys just expired. Fail-closed: every request gets a 401 — your gateway just converted an identity-provider blip into a full outage of every API behind it. Fail-open: you serve unauthenticated traffic. The production answer is neither: cache keys with a long TTL plus background refresh, serve stale keys when a refresh fails, and alert — never fetch JWKS on the request path. This is the single-point-of-failure pitfall below in miniature: any policy stage that calls out to an external dependency imports that dependency's availability into every request the gateway fronts.
Pitfalls
- Cramming business logic into NGINX/Lua and calling it a gateway. Response aggregation and conditional routing written as proxy scripts have no API contract, are painful to unit-test, and quietly become a distributed monolith living in a config file. If you need real transformation, use a purpose-built gateway or a BFF service.
- The gateway becomes a single point of failure and a deploy bottleneck. Every team's routes live in one config; one bad route reload can drop all north-south traffic. Run it HA with multiple instances, canary config changes, and isolate per-team route config.
- Aggregation couples the gateway to service schemas. If the gateway joins
orders+shippingresponses, a field rename in either service breaks the gateway. Keep gateway aggregation thin, or push it into a Backend-for-Frontend that a client team owns. - Per-request JWT verification without caching. RS256 signature checks are CPU-heavy; if you fetch JWKS or re-verify on every call you cap throughput. Cache the JWKS keys (and consider caching decode results per short window).
- Rate limits are only as good as the paths they see. If some clients reach a service through a separate reverse-proxy path that bypasses the gateway, your per-consumer quotas are silently wrong. All ingress for a service must funnel through the same enforcement point.
- Stacking hops for no reason. CDN → edge reverse proxy → gateway → mesh sidecar → service is four TLS terminations and four hops. Each is justified separately; adding one "because the diagram had it" just spends latency and money.
When to use which — and the trade-offs
Reach for a plain reverse proxy when routing decisions are envelope-level (host/path), TLS termination + load balancing + static-content caching are the job, and your backends already enforce their own auth. Signals: a single app or a handful of stable services, latency-sensitive traffic, a small ops team that wants one boring config.
Reach for an API gateway when you have many microservices that need one enforcement point for cross-cutting concerns: centralized authN/authZ, per-consumer rate limits and quotas, API keys, request/response transformation, protocol translation (REST↔gRPC), versioning, a developer portal, or client-facing aggregation. Signals: you are duplicating auth code across services, or clients complain about chatty multi-call flows.
What each costs
- Gateway gains a clean client contract and DRY policy — but costs an extra hop (~5–15 ms), a new SPOF and deploy chokepoint, real operational complexity, and the standing temptation to grow into a god-object as aggregation logic creeps in.
- Reverse proxy gains simplicity and near-zero latency — but costs you every cross-cutting concern pushed back into each service: duplicated auth, inconsistent (and un-coordinated) rate limits, no unified API view.
Versus a named alternative — the service mesh
A service mesh (Istio/Linkerd sidecars) also does routing, retries, mTLS, and rate limiting — but for east-west service-to-service traffic, per pod, not at the client edge. It is not a gateway replacement; they compose. Choose a reverse proxy when routing is envelope-level and services own their auth; choose an API gateway when you need one north-south enforcement point for application policy across many services; reach for a service mesh when the hard problem is service-to-service, not client-to-system.
Takeaways
- A reverse proxy routes on the envelope (SNI/Host/path) and forwards bytes; a gateway parses the message and enforces API policy. The gateway is usually a reverse proxy plus a policy layer, not a rival to it.
- Depth of inspection = latency: a pure reverse proxy adds ~1–2 ms, a gateway ~5–15 ms for auth, limiting, and transformation. Pay it only where the policy earns its keep.
- Keep aggregation and business logic thin or out of the gateway entirely; a fat gateway is a distributed-monolith chokepoint and a SPOF.
- Real stacks often run both: an edge reverse proxy or CDN for TLS + LB + caching, then a gateway for auth + routing across services.
Re-authored and deepened for this guide, drawing on the NGINX reverse-proxy and load-balancing documentation, the Envoy proxy architecture docs, the Kong Gateway and AWS API Gateway documentation, Chris Richardson's API Gateway and Backend-for-Frontend patterns on microservices.io, and Sam Newman's Building Microservices
(O'Reilly).
🤖 Don't fully get this? Learn it with Claude
Stuck on API Gateway vs Reverse Proxy? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **API Gateway vs Reverse Proxy** (System Design) and want to truly understand it. Explain API Gateway vs Reverse Proxy from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **API Gateway vs Reverse Proxy** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **API Gateway vs Reverse Proxy** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **API Gateway vs Reverse Proxy** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.