# API Gateways: One Entry Point, Every Cross-Cutting Concern

## Systems Design

| # | Post | What it covers |
|---|------|----------------|
| 00 | [APIs & Communication: How Services Talk to Each Other](/apis-communication-how-services-talk-to-each-other) | How services talk to each other shapes everything about a system. Nine concepts covering REST, WebSockets, async patterns, and API gateways. (146 chars) |
| 01 | [API Design: Building Contracts That Last](/api-design-building-contracts-that-last) | A great API is a contract that outlasts your code. Here are the principles that make APIs intuitive to consume, safe to evolve, and cheap to maintain. (154 chars) |
| 02 | [REST APIs: Constraints That Create Benefits](/rest-apis-constraints-that-create-benefits) | REST isn't just HTTP with JSON. It's an architectural style with specific constraints — and understanding them explains why REST APIs are designed the way they are. (166 chars) |
| 03 | [Authentication vs Authorisation: Two Questions, Two Checks](/authentication-vs-authorisation-two-questions-two-checks) | Authentication is who you are. Authorisation is what you're allowed to do. Confusing them is one of the most common security mistakes in system design. (153 chars) |
| 04 | [Session vs Token Authentication: Stateful vs Stateless Identity](/session-vs-token-authentication-stateful-vs-stateless-identity) | Session auth stores identity on the server. Token auth encodes it in the token. Here's how each works, where each breaks, and how to choose. (144 chars) |
| 05 | [OAuth 2.0 & OpenID Connect: Delegated Access and Federated Identity](/oauth-20-openid-connect-delegated-access-and-federated-identity) | OAuth 2.0 lets users grant apps access without sharing passwords. OpenID Connect adds identity on top. Here's how both actually work. (137 chars) |
| 06 | [JWT: What's Actually Inside the Token](/jwt-whats-actually-inside-the-token) | JWTs are everywhere in modern auth — and frequently misused. Here's exactly what a JWT contains, how the signature works, and what it doesn't protect. (153 chars) |
| 07 | [WebSockets: Real-Time Bidirectional Communication](/websockets-real-time-bidirectional-communication) | HTTP is request-response. WebSockets are a persistent two-way channel. Here's how they work, when to use them, and what to watch out for at scale. (151 chars) |
| 08 | [Long Polling, SSE & Webhooks: The Server-Push Spectrum](/long-polling-sse-webhooks-the-server-push-spectrum) | Three patterns for server-push communication — long polling, server-sent events, and webhooks. Here's how each works and when to reach for each. (150 chars) |
| 09 | [Sync vs Async Communication: The Architectural Fork](/sync-vs-async-communication-the-architectural-fork) | Synchronous services couple tightly. Asynchronous services decouple — but add complexity. Here's how to reason about which your system needs. (147 chars) |
| 10 | **API Gateways: One Entry Point, Every Cross-Cutting Concern** ← you are here | An API gateway centralises auth, rate limiting, routing, and observability for all your services. Here's what it does, how it works, and when you need one. (158 chars) |
| 11 | [APIs & Communication: Wrap-Up](/apis-communication-wrap-up) | A complete recap of all ten API and communication concepts — REST, auth, JWT, WebSockets, webhooks, async patterns, and API gateways — and how they connect. (161 chars) |

---

# API Gateways: One Entry Point, Every Cross-Cutting Concern

## The problem

Your URL shortener platform has grown into five distinct services: the link service, the analytics service, the user service, the webhook service, and the billing service. Each has its own HTTP API. Each is independently deployed. Each needs authentication, rate limiting, and request logging.

Six months in you notice the pattern: every service has its own authentication middleware — each slightly different. The link service rate limits at 100 requests per minute, the analytics service at 50, the billing service at 10 — all implemented separately, with no coordination. Logging is inconsistent — some services log request IDs, some don't. You add a new endpoint to the link service and forget to add rate limiting. A developer integrating the API needs to know five different base URLs, each with slightly different authentication behaviour.

Cross-cutting concerns — the capabilities every service needs, applied to every request — are being implemented five times, drifting apart, and creating maintenance overhead that scales with the number of services.

An API gateway centralises these concerns in one place: every external request passes through a single entry point that handles authentication, rate limiting, routing, logging, and request transformation consistently, before the request reaches any service.

---

## The core idea

An API gateway is a reverse proxy that sits in front of your backend services and handles cross-cutting concerns centrally. It receives all incoming external requests, applies policies (authentication, rate limiting, transformation), routes requests to the appropriate backend service, and returns the response to the client.

The backend services become internal — consumers interact only with the gateway's surface. The gateway is the API as far as external consumers are concerned.

---

## The analogy: airport security

An airport has dozens of airlines serving hundreds of destinations. Rather than each airline running its own security screening at their gate, there is a single mandatory security checkpoint that all passengers pass through, regardless of which airline or destination.

The checkpoint applies consistent standards: ID verification (authentication), bag screening (request inspection), prohibited items (rate limits, policy enforcement). Once through, passengers are routed to the appropriate gate (the backend service) based on their ticket (the request).

The airlines don't each build or operate security. They rely on a centralised system that applies consistent standards to everyone. Adding a new airline doesn't add a new security checkpoint — it just adds a new gate behind the existing one.

---

## What an API gateway does

### Authentication and authorisation

Rather than each service validating tokens independently, the gateway validates the token once and passes identity to services via trusted headers:

```
External request:
  GET /links/x7Kp2
  Authorization: Bearer eyJ...

Gateway:
  1. Validate JWT (signature, expiry, issuer, audience)
  2. Extract claims {user_id: 4821, role: "editor"}
  3. Forward to link service with headers:
     X-User-ID: 4821
     X-User-Role: editor
     X-Auth-Verified: true

Link service:
  Trusts X-Auth-Verified (request can only arrive via gateway)
  Proceeds directly to authorisation (is this user allowed to see this link?)
```

Backend services are only accessible via the gateway — firewall rules prevent direct external access. They trust the gateway's identity headers and don't need to validate tokens themselves. Authentication logic lives in one place.

### Rate limiting

The gateway enforces rate limits before requests reach backend services, protecting them from overload:

```
Rate limiting strategies:

Per-consumer:
  Free tier API keys:    100 req/min
  Pro tier API keys:    1000 req/min
  Partner API keys:    10000 req/min

Per-endpoint:
  POST /links:          20 req/min   (creation is expensive)
  GET  /links/{id}:   1000 req/min   (reads are cheap)
  POST /auth/login:      5 req/min   (brute force protection)

Per-IP (unauthenticated):
  All endpoints:         10 req/min  (spam protection)
```

Rate limit responses return `429 Too Many Requests` with `Retry-After` headers indicating when the client can retry.

### Routing

The gateway maps external URLs to internal service endpoints, providing a stable external API surface that can be changed independently of the backend:

```
External URL                         Internal URL
─────────────────────────────────────────────────────────
GET  /links/{id}          ─────►  link-service:8080/links/{id}
GET  /analytics/links/{id} ────►  analytics-service:8081/links/{id}
POST /auth/login           ────►  user-service:8082/auth/login
GET  /billing/usage        ────►  billing-service:8083/usage
```

This decouples the external API surface from internal service structure. The link service can be split into two services, refactored, or migrated to a different framework — the gateway routing is updated, and consumers see no change.

### Request and response transformation

Gateways can modify requests and responses as they pass through:

```
Request transformation (before forwarding to backend):
  ├── Add headers (correlation IDs, auth headers)
  ├── Remove headers (internal headers that shouldn't reach clients)
  ├── Rewrite paths (/v2/links → /links with version header)
  └── Inject query parameters (add tenant_id from auth token)

Response transformation (before returning to client):
  ├── Add headers (CORS, security headers, rate limit info)
  ├── Remove fields (internal fields consumers shouldn't see)
  ├── Convert formats (XML backend → JSON response for consumers)
  └── Aggregate responses (combine data from multiple services)
```

### Observability

The gateway is uniquely positioned to observe every request across all services:

```
Per-request logging:
  {
    "request_id": "req_abc123",
    "timestamp": "2026-01-15T09:30:00.142Z",
    "method": "GET",
    "path": "/links/x7Kp2",
    "user_id": "4821",
    "consumer_tier": "pro",
    "upstream_service": "link-service",
    "status": 200,
    "latency_ms": 23,
    "cache": "HIT"
  }
```

Every request across every service, with consistent fields, from a single source. No per-service logging configuration, no inconsistent fields. The request ID (correlation ID) propagates to backend services — when a request fails, you can trace it through every layer.

### SSL termination

Like CDN edge nodes, API gateways typically terminate TLS. Backend services communicate over HTTP on a private network:

```
Client ──HTTPS──► API Gateway (TLS terminates here) ──HTTP──► Backend Services
```

---

## Gateway patterns

### Edge gateway (BFF — Backend for Frontend)

A single gateway for all consumers. Simple, but can become a bottleneck as different consumers need different policies. Works well for platforms with similar consumers (all REST API consumers, all using the same auth mechanism).

### Backend for Frontend (BFF)

Separate gateways for different client types — web, mobile, third-party. Each gateway is optimised for its consumer:

```
Web BFF:
  ├── Session-based auth (cookies)
  ├── Returns rich responses (full data for dashboard)
  └── Handles web-specific CORS and CSP

Mobile BFF:
  ├── Token-based auth (JWT)
  ├── Returns compact responses (reduced bandwidth)
  └── Handles push notification token management

Partner API Gateway:
  ├── API key auth
  ├── Rate limits tuned for integration patterns
  └── Webhook management endpoints
```

The BFF pattern lets each gateway evolve independently based on its consumer's needs. The URL shortener platform would benefit from a BFF pattern: the internal web/mobile app has different auth and response needs than the public partner API.

### Service mesh vs API gateway

An API gateway handles north-south traffic — communication between external consumers and your services. A service mesh (Istio, Linkerd) handles east-west traffic — communication between internal services.

They solve different problems and are often used together:

```
External Consumer
       │
       ▼
  API Gateway       ← auth, rate limiting, external routing
       │
  ┌────┼────┐
  │    │    │
  ▼    ▼    ▼
Svc A → Svc B      ← Service Mesh: mTLS, retries, circuit breaking
  │         │         between internal services
  └─── C ───┘
```

---

## API gateway products

**Managed (cloud):**
- AWS API Gateway — deep AWS integration, pay-per-request pricing
- Google Cloud API Gateway — similar, GCP-native
- Azure API Management — feature-rich, enterprise-focused

**Self-hosted / open source:**
- Kong — widely deployed, plugin architecture, Kubernetes-native
- Traefik — lightweight, built for containers and Kubernetes
- NGINX — configurable, high-performance, lower-level

**SaaS:**
- Apigee (Google) — enterprise API management platform
- AWS App Mesh — for microservices on AWS

**For the URL shortener platform:** Kong or AWS API Gateway depending on infrastructure preference. Kong running on Kubernetes provides routing, auth plugins, and rate limiting with full control. AWS API Gateway provides the same with less operational overhead if the platform is AWS-native.

---

## The tradeoffs

**Single point of failure.** The API gateway becomes the entry point for all external traffic — which makes it a potential SPOF. Mitigations: deploy multiple gateway instances behind a load balancer, run across multiple availability zones, use managed gateways with built-in HA.

**Latency.** Every request passes through the gateway, adding a network hop. For simple pass-through requests this is typically 1–5ms. For requests requiring complex policy evaluation (multiple rate limit checks, request transformation), it can be more. Monitor gateway latency as a baseline metric.

**Configuration complexity.** A gateway that handles routing, auth, rate limiting, transformation, and observability for dozens of services has significant configuration complexity. Version-control gateway configuration, test changes in staging, and treat gateway config as code — not a manual configuration surface.

**Not a replacement for service-level security.** The gateway validates authentication and applies rate limits. It doesn't replace authorisation checks in individual services, input validation in services, or security hardening of backend services. Treat the gateway as a first line of defence, not the only one. Backend services should not blindly trust all traffic that arrives via the gateway — validate that requests genuinely came from the gateway (shared secret, network policy) and still perform authorisation.

---

## The one thing to remember

> **An API gateway solves the cross-cutting concern problem: authentication, rate limiting, routing, and observability implemented once, consistently, for every service — not reimplemented per service with inevitable drift.** The gateway is not where business logic lives. It's where infrastructure concerns live. Keep it thin, keep it fast, version-control its configuration, and ensure it's as highly available as the services it protects.

---

*← Previous: **[Sync vs Async Communication](/sync-vs-async-communication-the-architectural-fork)** — so far we've covered how to communicate; the next post covers the architectural choice of whether to wait for the response.*

*→ Next: **[APIs & Communication — Wrap-up](/apis-communication-wrap-up)** — all ten concepts pulled together, showing how they connect and what they set up for the pillars ahead.*


