Resilience4j Patterns: Circuit Breaker, Retry, Bulkhead, Rate Limiter, Time Limiter
Fast recall
Quick revision
Core answer
Practical resilience engineering knowledge and pattern composition
Using only retry (amplifies outages); combining patterns in wrong order; retrying on non-idempotent calls; no fallback
Discuss pattern ordering, retry storm risk, exponential backoff with jitter, circuit-breaker state machine (closed/open/half-open), and the thread-pool bulkhead vs semaphore bulkhead distinction
Interview-ready guide
Interview answer
Microservices talk to each other over networks. Networks fail, services get slow, pods restart, databases have spikes. Without resilience patterns, one slow downstream cascades: requests pile up, threads exhaust, the service becomes unresponsive, and failure propagates upstream.
Resilience4j is the JVM standard in 2026 — Netflix Hystrix was deprecated in 2020. Five complementary patterns:
Circuit Breaker
- Monitors failure rate of a dependency; when it crosses a threshold, trips open
- Fails fast during the cooldown instead of sending doomed requests
- Three states: CLOSED (normal), OPEN (tripped), HALF_OPEN (testing recovery)
- Resilience4j adds slow-call detection that Hystrix didn't have
Retry
- For transient failures: network blips, brief 503s, connection resets
- Exponential backoff with jitter; not linear or zero-delay
- Never retry non-idempotent operations without idempotency keys; duplicate charges result
- Typical: 3 attempts, 500ms start, 2x multiplier, 50% jitter
Bulkhead
- Limits concurrent in-flight calls to one dependency
- If downstream becomes slow, only N threads wait on it; rest of service keeps serving
- Semaphore type (lightweight) is default; thread-pool type for better isolation
- Prevents slow dependencies from sinking the whole service
Rate Limiter
- Caps outgoing call rate; respects downstream quotas
- Not for DDoS defense (that's API Gateway); for protecting downstream and respecting agreements
Time Limiter
- Enforces per-call deadline; requires method to return CompletableFuture
- Default socket timeouts are often 30 seconds; too long for user-facing paths
- Cut off at 2 to 5 seconds
The composition order matters
- From outermost to innermost: TimeLimiter, CircuitBreaker, Retry, Bulkhead, RateLimiter, then the actual call
- TimeLimiter first: overall deadline is enforced even if retries chain
- CircuitBreaker next: if circuit is open, short-circuit immediately; don't retry doomed calls
- Retry inside circuit: retries contribute to circuit's failure count; several retries can trip the circuit
- Bulkhead inside retry: each retry attempt passes through bulkhead; prevents retry storm
- RateLimiter innermost: paces the actual call to downstream
Annotation order in Spring Boot
- @TimeLimiter, @CircuitBreaker, @Retry, @Bulkhead, @RateLimiter; outermost first
- Resilience4j's Spring integration applies them in this documented order
Fallbacks are essential
- Return cached last-known value, default, deferred queue, degraded response
- Never call another service from a fallback; it can fail too
- Log and metric every fallback; alert on fallback rate
- Silent fallbacks hide real problems
Dangerous anti-patterns
- Retry without circuit breaker: one downstream outage becomes 3x load, prevents recovery
- No jitter: synchronized retry waves hammer downstream in pulses
- Retrying POST /charge without idempotency key: duplicate charges
- Too-long timeouts: 30-second default socket timeout means one slow call blocks a thread for 30 seconds
- No fallback: caller sees stack traces and 500 errors
Bulkhead types
- Semaphore (default, lightweight): limits concurrent calls using caller thread
- ThreadPool: separate thread pool per dependency; caller thread freed; better isolation but more overhead
- Semaphore is fine for most Spring Boot services
Service mesh vs app-level
- Istio/Linkerd provide retries, circuit breaking at network layer
- Resilience4j at app layer
- Use both: service mesh for generic HTTP resilience; Resilience4j for business-specific patterns with fallbacks
Monitoring is essential
- Resilience4j exposes Prometheus metrics: circuit state, retry count, bulkhead saturation
- Dashboard per dependency; alert on circuit OPEN, high fallback rate
The strategic answer
- Five patterns, applied in the right order, make services resilient to downstream failure
- Retry alone amplifies outages; circuit breaker stops the storm
- Always pair patterns with fallbacks and idempotency
- Test with chaos engineering; verify circuits actually trip and fallbacks fire
- Tune based on observed traffic; don't blindly copy tutorial defaults
Resilience4j Patterns: Circuit Breaker, Retry, Bulkhead, Rate Limiter, Time Limiter
Direct Answer
Five complementary patterns from Resilience4j (the 2026 standard replacing Hystrix): Circuit Breaker trips open on sustained failure to stop hammering a broken dependency; Retry handles transient failures with exponential backoff + jitter; Bulkhead limits concurrent calls to one dependency so it can't exhaust threads for the whole service; Rate Limiter caps outgoing call rate to respect downstream limits; Time Limiter enforces per-call deadlines. Combine in order: TimeLimiter → CircuitBreaker → Retry → Bulkhead → RateLimiter around the downstream call. Always pair with fallbacks and idempotency.
Common Mistakes & Pitfalls
Using only retry (amplifies outages); combining patterns in wrong order; retrying on non-idempotent calls; no fallback
Check your understanding
Answer these without looking back at the article.
- How does Resilience4j's slow-call detection differ from Hystrix's approach?
- When do you choose semaphore bulkhead vs thread-pool bulkhead?
- How do you make a POST endpoint safely retryable with idempotency keys?
- How does service mesh resilience (Istio) compare to Resilience4j?
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.