Skip to main content
Microservices · Topic 2 of 10

API Gateway

An API gateway is the single entry point for external clients. It routes requests to the right service and handles cross-cutting concerns once, instead of in every service.

Definition​

An API gateway is the single front door for clients. It sends each request to the right service and handles shared jobs such as authentication, rate limiting and TLS.

Why it exists​

Without a gateway, clients must know every service address and each service repeats the same checks. A gateway hides the internal layout behind one stable address.

How it works​

Typical responsibilities​

  • Routing by path, host, header or method.
  • Authentication (validate JWT) and coarse authorization.
  • Rate limiting and quotas.
  • TLS termination, CORS, request/response header manipulation.
  • Resilience: timeouts, retries and circuit breakers on downstream calls.
  • Observability: access logs, metrics, trace-ID creation.

Keep business logic out of the gateway. A gateway that orchestrates domain workflows becomes a bottleneck and a single team's dependency.

Example code​

Spring Cloud Gateway​

Built on Spring WebFlux (reactive, Netty). Three core terms:

  • Route: an ID, a destination URI, predicates and filters.
  • Predicate: a condition that must match (path, method, header...).
  • Filter: modifies the request or response (strip prefix, add header, rate limit...).
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service # resolved via service discovery + load balancer
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
- name: CircuitBreaker
args:
name: orderCb
fallbackUri: forward:/fallback/orders
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@userKeyResolver}"

Matching GET /api/orders/42: StripPrefix=1 removes /api, so the order service receives /orders/42. lb://order-service asks the load balancer for an instance registered under that name (see Service Discovery).

The key resolver decides who is being limited:

@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst("X-User-Id"))
.defaultIfEmpty("anonymous");
}

A custom global filter​

@Component
public class CorrelationIdFilter implements GlobalFilter, Ordered {

private static final String HEADER = "X-Correlation-Id";

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String id = exchange.getRequest().getHeaders().getFirst(HEADER);
if (id == null) {
id = UUID.randomUUID().toString();
}
ServerHttpRequest request = exchange.getRequest().mutate().header(HEADER, id).build();
return chain.filter(exchange.mutate().request(request).build());
}

@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}

Never block inside a gateway filter: it runs on a small number of event-loop threads.

System design considerations​

  • Run several instances and keep the gateway stateless
  • Set timeouts and circuit breakers on every upstream call
  • Apply rate limits and authentication at the edge, and authorise again inside services

When to use it, and when not​

Use it when

  • Many clients call many services and you want one stable entry point
  • You apply authentication, rate limiting and routing in one place
  • Different clients need different aggregated responses (BFF)

Think twice when

  • The gateway would contain business rules or heavy aggregation logic
  • One shared gateway becomes a team bottleneck
  • A simple load balancer is enough for a single service

Gateway versus Backend-for-Frontend (BFF)​

A BFF is a gateway tailored to one client type (web, mobile), shaping and aggregating data for that UI. Use a generic gateway for routing and policy, and BFFs where clients genuinely need different payloads.

Common mistakes​

  • Business logic or heavy aggregation in the gateway.
  • Blocking calls inside reactive filters.
  • Forgetting timeouts, so slow services exhaust gateway resources.
  • Exposing internal service ports directly, bypassing the gateway's security.

Interview questions​

1. Why do we need an API gateway?

To give clients one stable entry point and centralise authentication, rate limiting, routing and monitoring, so internal services can change freely and stay simple.

2. What are the downsides?

It is a potential single point of failure and a latency hop, so run multiple instances, keep it thin and monitor it closely.

3. How is the gateway different from a load balancer?

A load balancer spreads traffic across identical instances (mostly L4/L7 without application awareness). A gateway understands APIs: path-based routing, auth, transformation, quotas.

4. Where should authentication happen?

Validate the token at the gateway for a fast reject, and still verify authorization inside services that own sensitive data (defence in depth). See the Security section.

5. How do you do rate limiting in a distributed gateway?

A shared store such as Redis keeps token-bucket counters, so all gateway instances see the same state.

6. Spring Cloud Gateway vs Zuul?

Zuul 1 was blocking servlet-based and is retired from Spring Cloud. Spring Cloud Gateway is non-blocking and the supported option.

Check yourself​

Quick quiz3 questions

1Which job belongs in the API gateway?

2What is a Backend-for-Frontend?

3What is a risk of a single gateway?

Key takeaways​

  • The gateway is for routing and cross-cutting policy, not business logic.
  • Spring Cloud Gateway: routes = predicates + filters, reactive.
  • lb:// URIs integrate with discovery; use Redis for distributed rate limits.
  • Run it highly available and keep it thin.
Next topicService discovery

Finished this page? Track your progress (saved only in your browser).