Spring Boot cookbook · Intermediate
Add retries and a circuit breaker with Resilience4j
Keep your service responsive when a downstream dependency becomes slow or fails.
Approach
Use the Resilience4j Spring Boot starter: @Retry for transient failures, @CircuitBreaker to fail fast when the dependency is unhealthy, with a fallback method. Configure thresholds in YAML and expose state via Actuator/metrics.
Solution
@Service
class RecommendationClient {
private final RestClient client;
RecommendationClient(RestClient recommendationsRestClient) { this.client = recommendationsRestClient; }
@CircuitBreaker(name = "recommendations", fallbackMethod = "fallback")
@Retry(name = "recommendations")
public List<ProductSummary> forUser(String userId) {
return client.get().uri("/users/{id}/recommendations", userId).retrieve()
.body(new ParameterizedTypeReference<>() {});
}
private List<ProductSummary> fallback(String userId, Throwable t) {
return popularProducts.cached(); // degrade gracefully
}
}
resilience4j:
circuitbreaker:
instances:
recommendations:
sliding-window-size: 50
failure-rate-threshold: 50
slow-call-duration-threshold: 2s
slow-call-rate-threshold: 50
wait-duration-in-open-state: 30s
retry:
instances:
recommendations:
max-attempts: 3
wait-duration: 200ms
enable-exponential-backoff: true
retry-exceptions: [org.springframework.web.client.ResourceAccessException]
Pitfalls
- Retrying inside an open circuit (order of aspects matters; check
circuitBreakerAspectOrder/retryAspectOrder). - Fallbacks that hide outages without metrics/alerts.
- No HTTP timeouts — the breaker can't detect slowness without them.
Variations
- Bulkheads to cap concurrent calls per dependency.
- Spring Cloud Circuit Breaker abstraction.
Further reading: Resilience4j: Spring Boot
Reference: https://resilience4j.readme.io/docs/getting-started-3
More Spring Boot recipes
- Add correlation IDs to Spring Boot logs
- Authenticate machine clients with API keys in Spring Security
- Cache service results in Redis with @Cacheable
- Consume Kafka messages with retries and a dead-letter topic
- Handle concurrent updates with optimistic locking
- Implement soft delete with Hibernate
- Make POST endpoints idempotent in Spring Boot
- Map entities to DTOs with MapStruct