Why this matters
API gateways sit in front of your services and control how every request enters your platform. As an API Engineer, you will:
- Publish new endpoints without exposing internal service details.
- Enforce authentication, authorization, and quotas consistently.
- Protect backends with throttling, caching, and request/response transformations.
- Roll out changes safely using canaries and blue/green routing.
- Collect metrics, logs, and traces at a single choke point.
Who this is for
Engineers who design, secure, and operate APIs in production: backend developers, platform engineers, SREs, and API product owners.
Prerequisites
- HTTP fundamentals (methods, status codes, headers, body).
- Basic auth concepts: API keys, OAuth2/JWT, mTLS.
- Familiarity with JSON/YAML and curl.
Learning path
Concept explained simply
An API gateway is a smart traffic controller for your services. It decides: where to send the request (routing), who is allowed (authn/z), how fast (rate limits), how to shape payloads (transformations), and how to report what happened (observability).
Mental model
Think of an airport checkpoint:
- Routing = directing passengers to the right gate.
- Auth = checking IDs/boarding passes (API keys/JWT).
- Limits = controlling crowd size (rate limiting/throttling).
- Transformations = converting currencies/units (headers/body changes).
- Observability = counting passengers and recording events (metrics/logs/traces).
Key building blocks
- Routes & Upstreams: Map public paths and methods to internal services. Include health checks and timeouts.
- AuthN/Z: API keys, JWT/OAuth2 introspection, mTLS for service-to-service, role/claim checks.
- Rate limiting & Throttling: Per consumer/IP/key limits; define bursts and sustained rates; return 429 on exceed.
- CORS: Control cross-origin requests for browsers; explicitly set allowed origins, methods, and headers.
- Transformations: Add/remove headers, rewrite paths, mask sensitive fields, normalize error formats.
- Caching: Cache GET responses based on URIs/headers; honor Cache-Control; invalidate on deploys as needed.
- Observability: Correlation IDs, structured logs, status/latency metrics, and distributed tracing.
- Deployment strategies: Blue/green, header-based canary, percentage rollouts with fast rollback.
Worked examples
Example 1 — Basic route with JWT + CORS
{
"service": {"name": "users", "url": "http://users-svc:8080"},
"route": {"paths": ["/api/v1/users"], "methods": ["GET", "POST"]},
"plugins": [
{"name": "jwt-validate", "config": {"issuer": "auth.example", "jwks": "https://auth.example/.well-known/jwks.json", "audience": "api"}},
{"name": "cors", "config": {"origins": ["https://app.example.com"], "methods": ["GET","POST"], "headers": ["Authorization","Content-Type"], "allowCredentials": true}}
]
}What happens:
- Requests without a valid JWT receive 401.
- Browser clients from the allowed origin can call without CORS errors.
Example 2 — Rate limit with burst control
{
"service": {"name": "public-feed", "url": "http://feed-svc:8080"},
"route": {"paths": ["/api/v1/feed"], "methods": ["GET"]},
"plugins": [
{"name": "rate-limit", "config": {"key": "ip", "limitPerMinute": 120, "burst": 30}}
]
}What happens:
- Up to 120 requests/min per IP with a short burst of 30 allowed; further requests return 429.
Example 3 — Header-based canary
{
"service": {"name": "payments-v1", "url": "http://payments-v1:8080"},
"altService": {"name": "payments-v2", "url": "http://payments-v2:8080"},
"route": {"paths": ["/api/v1/payments"], "methods": ["POST"]},
"plugins": [
{"name": "route-by-header", "config": {"header": "X-Canary", "value": "true", "toService": "payments-v2"}},
{"name": "observability", "config": {"includeHeader": "X-Canary"}}
]
}What happens:
- Requests with
X-Canary: truego to v2; others go to v1. Rollback by removing the rule.
How to configure safely (step-by-step)
- Define upstream services with timeouts and retries.
- Create routes with explicit methods and path prefixes.
- Add authentication: start with the simplest standard that meets requirements (API key for server-to-server, JWT/OAuth2 for user flows, mTLS internally).
- Apply rate limits per consumer/key; add request size limits for protection.
- Set CORS explicitly: allowed origins, methods, headers; keep the list minimal.
- Add transformations only where necessary; prefer backend changes over complex gateway rewrites.
- Enable logs, metrics, tracing; propagate a correlation ID (generate if missing).
- Release with a canary and a rollback plan.
Exercises
These mirror the tasks in the Exercises panel below. You can complete them conceptually here and then compare with the provided solutions.
Exercise 1 — Secure Orders endpoint with API key, rate limit, and CORS
Goal: Expose /api/v1/orders to the orders-svc:8080 upstream. Require an API key in header X-API-Key, limit to 100 requests/min per key, allow CORS from https://app.example.com for GET and POST.
- Create the service and route.
- Enable API key auth and rate limiting per key.
- Enable CORS only for the specified origin and methods.
- Return 401 if key missing/invalid, 429 if over limit.
Self-check
- 401 without key, 200 with valid key.
- 429 after exceeding 100 requests/min with the same key.
- Preflight
OPTIONSsucceeds for the allowed origin.
Exercise 2 — Canary search endpoint
Goal: Route /api/v1/search to search-v1 by default, but send requests with header X-Canary: true to search-v2. Add observability to distinguish traffic.
- Create two upstreams and one public route.
- Add header-based routing rule.
- Tag logs/metrics with the header value for dashboards.
- Rollback by removing the rule or pointing canary to v1.
Self-check
- Without the header -> v1; with
X-Canary: true-> v2. - Dashboards show canary share over time.
Common mistakes and how to self-check
- Overly broad routes: Catch-all paths expose unintended endpoints. Self-check: verify each path and method explicitly.
- Permissive CORS: Using
*for credentials flows. Self-check: list exact origins and methods; test with browser devtools. - Missing timeouts/retries: Gateway threads hang. Self-check: set timeouts; simulate slow upstreams.
- Unlimited payload sizes: Risk of memory pressure. Self-check: set max request/response size.
- Rate limits on IP for mobile/NAT: Legit users blocked. Self-check: use consumer/key-based limits when possible.
- Silent transforms: Hidden behavior drifts from backend. Self-check: document every transformation and unit test critical ones.
- No correlation ID: Hard to trace issues. Self-check: ensure an
X-Request-IDexists and is propagated.
Practical projects
- Project A: Publish a read-only public API with per-key rate limits and cache GETs for 60s. Include a dashboard with request rate, p95 latency, and 4xx/5xx rate.
- Project B: Migrate an existing endpoint using blue/green. Roll to green, measure error/latency, then swap back if thresholds breach.
- Project C: Implement JWT auth with JWKS caching and automatic key rotation, plus role-based route guards.
Mini challenge
You must allow partner traffic from two origins with credentials, while blocking all others. Add per-partner 200 req/min limits and ensure preflight requests succeed. Write a short pseudo-config and list three curl commands you would use to verify behavior.
Hint
- Combine CORS with explicit origins and
Access-Control-Allow-Credentials: true. - Rate limit keyed by the API key or partner ID.
- Test: preflight OPTIONS, allowed origin request, disallowed origin request.
Next steps
- Automate gateway configuration as code with version control and reviews.
- Add synthetic checks that validate routing, auth, and limits continuously.
- Define SLOs for gateway latency and error rate; alert on burn rate.
Quick Test
The quick test is available to everyone. Only logged-in users will have their progress saved.