Spring Cloud Gateway CircuitBreaker Filter — Edge-Layer Resilience4j Integration
Fast recall
Quick revision
Core answer
CircuitBreaker GatewayFilter backed by Spring Cloud Circuit Breaker — a facade that by default uses Resilience4j. Declare it per-route in application.yml with name and optional fallbackUri; the filter wraps every routed request, tripping on 5xx/timeouts and routing to the fallback URI (another route or a @Controller endpoint) when OPEN. Unlike @CircuitBreaker annotations at the service layer (which protect each internal call site), the Gateway filter protects the edge — any downstream route, one policy per route, no service code changes required. Best combined: Gateway-level fuses for public-facing routes; service-level @CircuitBreaker for specific critical call sites inside services.Whether you understand that Spring Cloud Gateway's CircuitBreaker filter is a distinct integration point — an edge-layer fuse — not the same as the service-level @CircuitBreaker annotation covered elsewhere
Confusing the GatewayFilter with the annotation; thinking both are needed for every service; not configuring fallbackUri so OPEN state bubbles up an ugly 5xx; forgetting that the filter's name maps to a CircuitBreakerRegistry bean
Walk through the layered defense model — edge fuses at the gateway, service-level fuses at call sites, with distinct failure domains; discuss the Spring Cloud Circuit Breaker abstraction (swap Resilience4j for Sentinel); show the fallback controller pattern; mention reactive flow specifics
Interview-ready guide
Interview answer
The core distinction
- Spring Cloud Gateway's CircuitBreaker GatewayFilter is a route-level fuse at the edge
- Service-level @CircuitBreaker annotations protect specific call sites inside services
- Both exist; they solve different problems
- Edge fuse protects external clients from a failing backend; service annotation protects internal call graphs
- Mature deployments have both — layered defense
The Spring Cloud Circuit Breaker abstraction
- Thin facade above Resilience4j (default) or Sentinel
- The Gateway filter uses the reactive variant
- Dependency: spring-cloud-starter-circuitbreaker-reactor-resilience4j
- Swap starters to move between Resilience4j and Sentinel without changing YAML
YAML-based route configuration
- Each route under spring.cloud.gateway.routes
- Filter name = CircuitBreaker
- Args: name (maps to CircuitBreakerRegistry instance), fallbackUri, statusCodes
- Resilience4j config under resilience4j.circuitbreaker.instances.
tunes the behaviour - Each route gets its own breaker instance — one outage doesn't trip others
Key arguments explained
- name is required — maps to the circuit-breaker bean
- fallbackUri is typically forward:/fallback/... pointing at a local controller
- statusCodes controls which HTTP statuses count as failure — defaults to 5xx; 4xx is the client's fault and does not trip
- Exception matching controlled globally via Resilience4j recordExceptions
Fallback controller pattern
- Annotated with @RestController, mapped to the fallbackUri path
- Returns Mono or ResponseEntity (reactive stack)
- Must be fast and local — Redis cache, static JSON, simple degraded message
- Never call another backend from a fallback; it can fail too
Programmatic RouteLocator alternative
- Same semantics as YAML in Java DSL
- RouteLocatorBuilder with .filters(f -> f.circuitBreaker(c -> c.setName...setFallbackUri...))
- Customizer
bean to tune defaults
TimeLimiter is packaged with the breaker
- Spring Cloud Circuit Breaker attaches a TimeLimiter alongside each CircuitBreaker
- timeoutDuration bounds the reactive call; cancels the downstream Mono on deadline
- Configured via Resilience4JConfigBuilder.timeLimiterConfig
Filter chaining for full edge resilience
- Order matters: RequestRateLimiter first, then Retry, then CircuitBreaker, then route
- RateLimiter rejects over-quota before anything else
- Retry's attempts contribute to CircuitBreaker stats
- CircuitBreaker short-circuits on OPEN
When gateway-level is the right layer
- Public API consumers need fast 5xx or cached fallback, not hanging
- Entire downstream service flapping — trip at the edge without touching service code
- SLO differentiation per route — stricter for payment, lax for catalog
- Quick toggle: flip filter to always-open during incident via config update
When service-level annotation is the right layer
- Internal service-to-service calls invisible to the gateway
- Per-call-site fallbacks with business logic
- Programmatic control over retry + circuit breaker composition
- Services with many downstream dependencies — one breaker per downstream at call site
Common pitfalls
- Name collisions across routes — sharing a breaker unintentionally
- Fallback that calls another backend — re-creates the fail-slow problem
- Blocking code in fallbacks on reactive stack — event loop block
- statusCodes overridden to include 4xx — client errors trip the breaker
- Not monitoring gateway breaker state — invisible outages
Observability
- /actuator/circuitbreakers exposes all instances and states
- Prometheus metric resilience4j_circuitbreaker_state tagged per instance
- Alert on OPEN sustained beyond 2 minutes
- Alert on HALF_OPEN to OPEN transitions — recovery attempt failed
- Alert on sustained fallback invocation rate — degraded experience
The layered defense model
- Gateway filter = fuse on the outside door of the building
- Service annotation = fuse on each appliance's plug
- Panel-only means one fault trips everything
- Appliance-only means unsafe panel wiring remains
- Both together is what mature deployments run
The strategic answer
- Gateway CircuitBreaker filter is the edge-layer fuse; service annotation is the call-site fuse
- Backed by the Spring Cloud Circuit Breaker abstraction; default Resilience4j reactive
- Per-route instance, declared in YAML or programmatic DSL
- Fallback URI must be local and fast; forward:/fallback/... to a controller
- Chain with RateLimiter and Retry for full edge resilience
- Monitor state; alert on sustained OPEN; use layered defense with service-level breakers
Spring Cloud Gateway CircuitBreaker Filter — Edge-Layer Resilience4j Integration
Direct Answer
Spring Cloud Gateway ships a built-in CircuitBreaker GatewayFilter backed by Spring Cloud Circuit Breaker — a facade that by default uses Resilience4j. Declare it per-route in application.yml with name and optional fallbackUri; the filter wraps every routed request, tripping on 5xx/timeouts and routing to the fallback URI (another route or a @Controller endpoint) when OPEN. Unlike @CircuitBreaker annotations at the service layer (which protect each internal call site), the Gateway filter protects the edge — any downstream route, one policy per route, no service code changes required. Best combined: Gateway-level fuses for public-facing routes; service-level @CircuitBreaker for specific critical call sites inside services.
Common Mistakes & Pitfalls
Confusing the GatewayFilter with the annotation; thinking both are needed for every service; not configuring fallbackUri so OPEN state bubbles up an ugly 5xx; forgetting that the filter's name maps to a CircuitBreakerRegistry bean
Check your understanding
Answer these without looking back at the article.
- How does the Spring Cloud Gateway CircuitBreaker filter chain with RequestRateLimiter and Retry filters, and what's the correct order?
- What's the right content for a fallback controller on the reactive Gateway stack — what must you avoid?
- How do you swap Resilience4j for Alibaba Sentinel under the Spring Cloud Circuit Breaker abstraction?
- Why must the Gateway's CircuitBreaker filter's `name` map to a unique Resilience4j instance per route, and what breaks if two routes share a name?
Related interview prep categories
2Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.