Spring Cloud Gateway
IntermediateSpring Cloud Gateway is a reactive API gateway built on Project Reactor; predicates match routes and filters (add headers, retry, rate-limit) process requests and responses.
Overview
Spring Cloud Gateway is a non-blocking API gateway built on top of Spring WebFlux and Project Reactor. It serves as the single entry point for all client traffic in a microservices architecture: routing requests to backend services, applying cross-cutting concerns (authentication, rate limiting, circuit breaking, logging), and transforming requests and responses. Routes are defined by **predicates** (match conditions: path, method, header, host) and **filters** (modify the request/response: add headers, strip path prefix, retry, rate-limit). Predicates and filters can be combined in application.yml or programmatically via `RouteLocator`. The reactive model means it handles thousands of concurrent connections with minimal threads.
Route Configuration with Predicates and Filters
Routes are evaluated in order (by `order` field, ascending). Each route has: `uri` (upstream service), `predicates` (match conditions), and `filters` (transformations). `StripPrefix=1` removes the first path segment before forwarding. `AddRequestHeader` injects headers. `RewritePath` rewrites the path with regex.
# application.yml
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service # lb:// → Spring Cloud LoadBalancer
predicates:
- Path=/api/orders/**
- Method=GET,POST
filters:
- StripPrefix=1 # /api/orders/123 → /orders/123
- AddRequestHeader=X-Gateway-Source, gateway
- name: CircuitBreaker
args:
name: order-service
fallbackUri: forward:/fallback/orders
- id: auth-service
uri: lb://auth-service
predicates:
- Path=/api/auth/**
filters:
- RewritePath=/api/auth/(?<segment>.*), /${segment}
# Default route — catch-all fallback
- id: monolith-fallback
uri: http://monolith:8080
predicates: [Path=/**]
order: 9999Rate Limiting and Authentication Filters
The `RequestRateLimiter` filter uses Redis to throttle requests per user. The `TokenRelay` filter forwards the Bearer token from the incoming request to upstream services. A custom `GlobalFilter` can implement gateway-level JWT validation, rejecting unauthenticated requests before they reach any service.
# Rate limiting with Redis (spring-boot-starter-data-redis required)
spring:
cloud:
gateway:
routes:
- id: api-route
uri: lb://api-service
predicates: [Path=/api/**]
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 10 req/s
redis-rate-limiter.burstCapacity: 20 # burst up to 20
key-resolver: "#{@userKeyResolver}" # throttle per user
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getHeaders()
.getFirst("X-User-Id") != null
? exchange.getRequest().getHeaders().getFirst("X-User-Id")
: "anonymous"
);
}
// JWT validation global filter
@Component
public class JwtGatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String auth = exchange.getRequest().getHeaders().getFirst("Authorization");
if (auth == null || !auth.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// validate JWT, add X-User-Id header
return chain.filter(exchange.mutate().request(
exchange.getRequest().mutate()
.header("X-User-Id", extractUserId(auth)).build()).build());
}
@Override public int getOrder() { return -1; } // run before routing
}Circuit Breaker and Retry Filters
The `CircuitBreaker` filter wraps upstream calls with Resilience4j; on failure it redirects to a `fallbackUri`. The `Retry` filter retries on specified status codes or exceptions. Both are configured per-route, allowing different resilience policies for different upstream services.
spring:
cloud:
gateway:
routes:
- id: payment-service
uri: lb://payment-service
predicates: [Path=/api/payments/**]
filters:
- name: Retry
args:
retries: 3
statuses: SERVICE_UNAVAILABLE,GATEWAY_TIMEOUT
methods: GET
backoff:
firstBackoff: 50ms
maxBackoff: 500ms
factor: 2
- name: CircuitBreaker
args:
name: payment-cb
fallbackUri: forward:/fallback/payment
- name: RequestSize # reject oversized request bodies
args: {maxSize: 5MB}
# Fallback controller
@RestController
class FallbackController {
@GetMapping("/fallback/payment")
ResponseEntity<?> paymentFallback() {
return ResponseEntity.status(503)
.body(Map.of("error", "Payment service temporarily unavailable"));
}
}Key Points to Remember
- 1Spring Cloud Gateway is non-blocking (WebFlux/Reactor) — handles high concurrency with few threads
- 2Routes: uri + predicates (match) + filters (transform) — evaluated by order field ascending
- 3StripPrefix removes path segments before forwarding; RewritePath transforms with regex
- 4RequestRateLimiter filter uses Redis token bucket — throttles per user/IP key
- 5GlobalFilter applies to ALL routes — use for authentication, request ID injection, logging
- 6CircuitBreaker filter wraps each upstream call with Resilience4j; fallbackUri handles failures
Interview Questions
Sign in to ask AriaWhat is the difference between a GlobalFilter and a GatewayFilter in Spring Cloud Gateway?
How would you implement rate limiting per authenticated user in Spring Cloud Gateway?
What does StripPrefix=1 do and when would you use it?
How does Spring Cloud Gateway integrate with Resilience4j for circuit breaking?
Why is Spring Cloud Gateway built on WebFlux instead of Spring MVC?
Ask Aria about Spring Cloud Gateway
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.