Resilience4j Circuit Breaker
IntermediateResilience4j is a lightweight fault-tolerance library providing CircuitBreaker, RateLimiter, Retry, Bulkhead, and TimeLimiter decorators for functional or reactive code.
Overview
Resilience4j is the de-facto standard fault-tolerance library for Spring Boot microservices, replacing the deprecated Hystrix. It provides six decorators: **CircuitBreaker** (stop calling a failing service), **Retry** (retry with backoff), **RateLimiter** (throttle calls per time window), **Bulkhead** (limit concurrent calls), **TimeLimiter** (enforce a timeout on async calls), and **Cache** (memoize results). All decorators are composable and work with `CompletableFuture`, reactive types, and plain functions. The **CircuitBreaker** uses a sliding window (count-based or time-based) to compute failure rates. When the rate exceeds a threshold, the circuit opens and subsequent calls immediately throw a `CallNotPermittedException`, giving the downstream service time to recover.
Circuit Breaker: States and Configuration
The CircuitBreaker has three states: **CLOSED** (normal, calls pass through), **OPEN** (failing, calls blocked for `waitDurationInOpenState`), **HALF_OPEN** (probe — a limited number of calls are allowed; if they succeed, circuit closes; if they fail, it reopens). Configuration is set in `application.yml` under `resilience4j.circuitbreaker.instances.<name>`.
# application.yml
resilience4j:
circuitbreaker:
instances:
payment-service:
slidingWindowType: COUNT_BASED # or TIME_BASED
slidingWindowSize: 10 # last 10 calls
failureRateThreshold: 50 # open if ≥50% fail
slowCallRateThreshold: 80 # open if ≥80% are slow
slowCallDurationThreshold: 2000ms
waitDurationInOpenState: 10s # stay open 10s before HALF_OPEN
permittedNumberOfCallsInHalfOpenState: 3
minimumNumberOfCalls: 5 # need at least 5 calls before evaluating
# Spring Boot Actuator exposes circuit breaker state:
# GET /actuator/circuitbreakers
# GET /actuator/circuitbreakerevents@CircuitBreaker on Service Methods
Annotate service methods with `@CircuitBreaker(name = "payment-service", fallbackMethod = "fallback")`. The fallback method must have the same signature plus a `Throwable` parameter. Combine with `@Retry` on the same method — decorators are applied in a specific order (Retry → CircuitBreaker → RateLimiter → TimeLimiter → Bulkhead).
@Service
public class OrderService {
@CircuitBreaker(name = "payment-service", fallbackMethod = "paymentFallback")
@Retry(name = "payment-service")
@TimeLimiter(name = "payment-service")
public CompletableFuture<PaymentResult> processPayment(Order order) {
return CompletableFuture.supplyAsync(
() -> paymentClient.charge(order.getId(), order.getAmount())
);
}
// Fallback — same return type + Throwable
public CompletableFuture<PaymentResult> paymentFallback(
Order order, Throwable ex) {
log.warn("Payment service unavailable: {}", ex.getMessage());
return CompletableFuture.completedFuture(
PaymentResult.deferred(order.getId()) // queue for later retry
);
}
}Retry and RateLimiter Configuration
`@Retry` retries on specific exceptions with exponential backoff and jitter. `@RateLimiter` limits calls per time window — callers block up to `timeoutDuration` waiting for a permit; after that, `RequestNotPermitted` is thrown. Both are configured in `application.yml` alongside the circuit breaker.
# application.yml
resilience4j:
retry:
instances:
payment-service:
maxAttempts: 3
waitDuration: 500ms
enableExponentialBackoff: true
exponentialBackoffMultiplier: 2.0
randomizedWaitFactor: 0.5 # jitter to avoid thundering herd
retryExceptions:
- java.net.ConnectException
- feign.RetryableException
ignoreExceptions:
- com.example.BusinessException # don't retry business errors
ratelimiter:
instances:
payment-service:
limitForPeriod: 100 # 100 calls per period
limitRefreshPeriod: 1s
timeoutDuration: 500ms # wait up to 500ms for a permitKey Points to Remember
- 1CircuitBreaker has three states: CLOSED (normal), OPEN (blocked), HALF_OPEN (probing)
- 2failureRateThreshold triggers OPEN; waitDurationInOpenState controls recovery pause
- 3Fallback method must have same signature as the decorated method plus a Throwable parameter
- 4Decorator order: Retry → CircuitBreaker → RateLimiter → TimeLimiter → Bulkhead
- 5@Retry uses exponential backoff + jitter to avoid thundering herd on recovery
- 6Expose circuit breaker state via Spring Actuator /actuator/circuitbreakers endpoint
Interview Questions
Sign in to ask AriaExplain the three states of a circuit breaker and the transitions between them.
What is the difference between a count-based and time-based sliding window in Resilience4j?
Why is it important to add jitter to retry backoff times?
What is the order in which Resilience4j decorators are applied?
How does the Bulkhead pattern differ from the Circuit Breaker pattern?
Ask Aria about Resilience4j Circuit Breaker
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.