API Gateway
An API gateway is a single entry point for all client requests. It handles routing to backend services, authentication, rate limiting, request transformation, and observability.
API Gateway = the front desk of a hotel. It checks your ID (auth), tells you which floor (routing), and limits how many people enter (rate limiting). But the front desk should NOT cook your food -- that's the kitchen's (service's) job.
API gateways consolidate cross-cutting concerns: auth (JWT validation, OAuth), rate limiting, SSL termination, request logging, and routing. Backend services don't need to implement these individually. Common implementations: AWS API Gateway, Kong, Nginx, Envoy, Apigee. In a microservices architecture, the gateway routes /users/* to the user service and /orders/* to the order service — clients see one endpoint.
API gateway patterns: BFF (Backend for Frontend) — a specialized gateway per client type (mobile BFF, web BFF) that aggregates and transforms data for the specific client's needs, reducing over-fetching and chattiness. GraphQL as API gateway — a single GraphQL schema over multiple microservices, enabling clients to request exactly the data they need. GraphQL federation (Apollo Federation) allows each microservice to own its portion of the schema. Gateway vs service mesh: a gateway manages north-south traffic (external clients to internal services); a service mesh manages east-west traffic (service to service). In production, both are used together. Rate limiting at the gateway: token bucket or sliding window per client API key. Centralized rate limiting requires a distributed counter (Redis) to aggregate limits across multiple gateway instances.
I'd place an API gateway at the edge for all external traffic — it's the right place for auth, rate limiting, and routing. I'd keep the gateway thin (routing + auth only) and push business logic into services to avoid the gateway becoming a bottleneck. For internal services, I'd use a service mesh (Istio) rather than routing internal calls through the external gateway. I'd implement rate limiting using a sliding window counter in Redis, keyed by (API_key, time_window) with atomic INCR + EXPIRE.
Building too much logic into the API gateway. Gateways that perform data transformation, business logic, or database queries become a shared bottleneck and single point of failure. Keep gateways as dumb routers; put logic in services.