API Gateway
Context
Section titled “Context”You have a dozen services, each with its own API and its own network address. A mobile app or a single-page web client needs data from several of them to render a single screen — the order summary alone touches Orders, Inventory, and Customer. If the client talks to each service directly, it has to know every service’s address, make many round trips over a slow mobile network, and implement authentication against each one.
Problem
Section titled “Problem”Exposing internal services directly to external clients couples those clients to your internal structure. The client must discover and call many endpoints, and every time you split or merge a service, every client breaks. Worse, cross-cutting concerns — authentication, TLS termination, rate limiting, request logging — would have to be implemented in every service or in every client. And a chatty client on a high-latency connection pays a round trip per service just to fill one screen. How do you give external clients one stable, efficient, secure place to call, without leaking your internal topology?
Solution
Section titled “Solution”An API Gateway is a single server that sits between external clients and the internal services. It is the one entry point to the system, and it does three jobs:
- Routing — it receives every external request and forwards it to the appropriate service, mapping a public path to an internal address. Clients know only the gateway.
- Aggregation — for a request that needs data from several services, the gateway can fan out, call each one, and compose a single response, so the client makes one call instead of many.
- Offloading cross-cutting concerns — authentication, authorization, TLS termination, rate limiting, request logging, and caching all happen once, at the edge, instead of being duplicated in every service.
flowchart LR Web[Web Client] --> GW Mobile[Mobile Client] --> GW ThirdParty[Third-party API client] --> GW GW[API Gateway<br/>routing - aggregation - auth - rate limit] GW --> O[Order Service] GW --> I[Inventory Service] GW --> C[Customer Service]
Example
Section titled “Example”Gateway behaviour is configuration, not application code: you declare routes and the policies that apply to them, and the gateway engine enforces them. Here is a route configuration that maps public paths to internal services and attaches authentication and rate limiting to each route.
# api-gateway.yaml — routes external paths to internal serviceslisten: ":443"tls: cert: /etc/gateway/tls.crt key: /etc/gateway/tls.key
routes: - path: /api/orders/* upstream: http://order-service methods: [GET, POST] auth: type: jwt issuer: https://auth.example.com rate_limit: requests_per_minute: 120
- path: /api/customers/* upstream: http://customer-service methods: [GET] auth: type: jwt issuer: https://auth.example.com rate_limit: requests_per_minute: 60
# An aggregating route: the gateway fans out and composes one response. - path: /api/order-summary/:id aggregate: - get: http://order-service/orders/:id # as "order" as: order - get: http://customer-service/customers/:customerId as: customer - get: http://inventory-service/stock/:sku as: stock auth: type: jwt issuer: https://auth.example.comResulting context
Section titled “Resulting context”What you gain:
- One simple entry point. Clients know a single host and a stable public API. Internal services can be split, merged, renamed, or moved without breaking any client.
- Cross-cutting concerns in one place. Authentication, TLS, rate limiting, and logging are configured once at the edge instead of being reimplemented in every service.
- Fewer round trips. Aggregation lets a client fill a whole screen with one request, which matters most on high-latency mobile connections.
What it costs you:
- A new component to build and operate. The gateway must itself be highly available and scalable, because it is on the critical path of every request. If it is down, the system is down.
- It can become a bottleneck or a God-object. As more routing rules, transformations, and aggregations accumulate, the gateway grows into a large, shared component that every team must change — and a development bottleneck when one team’s change waits behind another’s.
- Risk of over-generalisation. A single gateway trying to serve a web app, a mobile app, and third-party integrations equally well tends to serve none of them ideally, because their needs differ.
That last cost is the motivation for the next pattern: instead of one gateway for everyone, give each client type its own. See Backends for Frontends.
Related patterns
Section titled “Related patterns”- Backends for Frontends — one tailored gateway per client type, addressing the God-object risk.
- Service Discovery — how the gateway finds live instances of the services it routes to.
- API Composition — the aggregation technique a gateway uses to join data from several services.