What an API gateway does
An API gateway sits between clients and your microservices. It handles:
- Routing:
/api/users/*goes to the user service,/api/orders/*goes to the order service - Authentication: verify JWTs before requests reach any service
- Rate limiting: enforce per-consumer limits in one place
- Logging: capture request metadata for every API call
- Transformation: add, remove, or modify headers and bodies
Why Kong
Kong is built on Nginx and runs as a reverse proxy. It is fast (sub-millisecond overhead for most plugins), extensible (200+ plugins), and can run in DB-less mode with declarative configuration.
Declarative configuration
# kong.yaml
_format_version: "3.0"
services:
- name: user-service
url: http://user-service:3000
routes:
- name: user-routes
paths:
- /api/users
strip_path: false
plugins:
- name: rate-limiting
config:
minute: 100
policy: redis
redis_host: redis
- name: order-service
url: http://order-service:3000
routes:
- name: order-routes
paths:
- /api/orders
strip_path: false
plugins:
- name: jwt
config:
claims_to_verify:
- exp
- name: correlation-id
config:
header_name: X-Trace-Id
generator: uuid
- name: file-log
config:
path: /dev/stdout
reopen: true
This configuration routes two services, enforces JWT authentication globally, adds trace IDs, logs every request, and rate-limits the user service at 100 requests per minute.
JWT authentication
Kong validates JWTs without your services knowing. The flow:
- Client sends
Authorization: Bearer <token> - Kong validates the signature, expiration, and issuer
- If valid, Kong forwards the request with decoded claims in headers
- If invalid, Kong returns 401 — the request never reaches your service
consumers:
- username: mobile-app
jwt_secrets:
- algorithm: RS256
key: mobile-app-iss
rsa_public_key: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
Rate limiting with Redis
For multiple Kong instances behind a load balancer, use Redis-backed rate limiting:
plugins:
- name: rate-limiting
config:
minute: 1000
hour: 10000
policy: redis
redis_host: redis
redis_port: 6379
redis_database: 0
fault_tolerant: true
fault_tolerant: true means if Redis is down, requests pass through unthrottled rather than being blocked. This is the right choice for most systems — rate limiting is a protection, not a gate.
Health checks and circuit breaking
Kong can health-check upstream services and stop routing to unhealthy ones:
services:
- name: user-service
url: http://user-service:3000
connect_timeout: 5000
read_timeout: 10000
retries: 2
healthchecks:
active:
http_path: /health
interval: 10
healthy:
successes: 3
unhealthy:
http_failures: 3
The deployment pattern
Client → Kong (gateway) → Service A
→ Service B
→ Service C
Kong runs as a Kubernetes Ingress Controller or as standalone Docker containers. We run it in DB-less mode — the YAML config is mounted as a ConfigMap. Changes go through Git, reviewed like code.
When not to use an API gateway
If you have fewer than three services, an API gateway adds complexity without proportional benefit. A simple Nginx reverse proxy or even Next.js API routes can handle routing and auth for a small system.
