Spring Boot Circuit Breaker — Complete Implementation Guide
In this tutorial, you will learn about Spring Boot Circuit Breaker. We cover key concepts, practical examples, and best practices to help you master this topic.
Spring Boot circuit breakers using Resilience4j provide annotation-driven circuit breaking, declarative fallback methods, and seamless integration with Spring's metrics and Actuator systems.
What You'll Learn
By the end of this tutorial, you will know how to configure Resilience4j in Spring Boot, annotate methods with @CircuitBreaker, implement fallback handlers, and monitor circuit state.
Why It Matters
Spring Boot is the most popular Java framework. Resilience4j is the recommended circuit breaker library for Spring Boot applications, replacing the deprecated Hystrix with better performance and more features.
Real-World Use
Durga Antivirus Pro's scanning API uses Spring Boot with Resilience4j circuit breakers around its malware signature lookup service, ensuring the scan endpoint degrades gracefully when the signature database is unreachable.
Spring Boot Circuit Breaker Learning Path
flowchart LR
A[Best Practices] --> B[Spring Boot Circuit Breaker]
B --> C[Resilience4j Config]
B --> D[Fallback Methods]
B --> E[Metrics Integration]
B --> F{You Are Here}
style F fill:#f90,color:#fff
Adding Resilience4j Dependencies
Add the Resilience4j Spring Boot starter to enable annotation-based circuit breakers.
// build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.1.0'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
# application.yml
resilience4j:
circuitbreaker:
configs:
default:
sliding-window-size: 10
minimum-number-of-calls: 5
failure-rate-threshold: 50
wait-duration-in-open-state: 30s
permitted-number-of-calls-in-half-open-state: 3
automatic-transition-from-open-to-half-open-enabled: true
Annotation-Based Circuit Breaker
The @CircuitBreaker annotation wraps any Spring bean method with circuit breaker logic.
@Service
public class FileScanService {
private static final Logger log = LoggerFactory.getLogger(FileScanService.class);
@CircuitBreaker(name = "signatureDatabase", fallbackMethod = "fallbackScan")
public ScanResult scanFile(byte[] fileContent) {
log.info("Scanning file via signature database");
ResponseEntity<ScanResult> response = restTemplate.postForEntity(
"https://signatures.dodatech.com/scan",
fileContent,
ScanResult.class
);
return response.getBody();
}
public ScanResult fallbackScan(byte[] fileContent, Throwable t) {
log.warn("Signature database unavailable, using cached signatures", t);
return ScanResult.cachedScan(fileContent);
}
}
Configuring Multiple Circuit Breakers
Different downstream services need different circuit breaker configurations.
@Configuration
public class CircuitBreakerConfig {
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultConfig() {
return factory -> {
factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
.circuitBreakerConfig(CircuitBreakerConfig.custom()
.slidingWindowSize(10)
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(30))
.build())
.timeLimiterConfig(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(5))
.build())
.build());
factory.configure(builder -> builder
.circuitBreakerConfig(CircuitBreakerConfig.custom()
.slidingWindowSize(5)
.failureRateThreshold(30)
.waitDurationInOpenState(Duration.ofSeconds(60))
.build())
.build(), "databaseService");
};
}
}
Monitoring with Actuator and Metrics
Resilience4j exposes circuit breaker metrics through Spring Boot Actuator.
@RestController
@RequestMapping("/health")
public class CircuitHealthController {
private final CircuitBreakerRegistry registry;
public CircuitHealthController(CircuitBreakerRegistry registry) {
this.registry = registry;
}
@GetMapping("/circuits")
public Map<String, String> getCircuitStates() {
Map<String, String> states = new HashMap<>();
registry.getAllCircuitBreakers().forEach(cb -> {
states.put(cb.getName(), cb.getState().name());
});
return states;
}
}
// GET /health/circuits
// {
// "signatureDatabase": "CLOSED",
// "databaseService": "OPEN",
// "notificationService": "HALF_OPEN"
// }
Event-Driven State Transitions
React to circuit breaker state changes with event listeners.
@Component
public class CircuitBreakerEventListener {
private static final Logger log = LoggerFactory.getLogger(CircuitBreakerEventListener.class);
@EventListener
public void onCircuitEvent(CircuitBreakerEvent event) {
if (event.getEventType() == CircuitBreakerEvent.Type.STATE_TRANSITION) {
log.warn("Circuit breaker '{}' transition: {} -> {}",
event.getCircuitBreakerName(),
event.getPreviousState(),
event.getCurrentState());
if (event.getCurrentState() == CircuitBreaker.State.OPEN) {
notificationService.sendAlert("Circuit opened for: " + event.getCircuitBreakerName());
}
}
}
}
Common Mistakes
Forgetting the fallbackMethod parameter -- The @CircuitBreaker annotation requires a fallbackMethod that matches the method signature plus a Throwable parameter. Missing it causes startup errors.
Using the same circuit breaker name for different services -- Each downstream service should have a uniquely named circuit breaker with its own configuration.
Not configuring a TimeLimiter -- Without a TimeLimiter, a slow request blocks the thread until completion. Add a timeout to Fail Fast and trip the circuit.
Placing @CircuitBreaker on private methods -- Spring AOP only works on public methods called from outside the class. Self-invocation bypasses the circuit breaker.
Ignoring the exception type in fallback methods -- The fallback method receives the exception as a parameter. Log it and handle different exception types differently.
Practice Questions
What dependency do you need to add for Resilience4j circuit breakers in Spring Boot 3? resilience4j-spring-boot3 with spring-boot-starter-aop.
How do you configure different settings for different circuit breakers? Use the Factory.configure() method with a circuit breaker name list. Each name gets its own configuration.
What does the sliding-window-size configuration control? The number of requests used to calculate the failure rate. A window size of 10 means the failure rate is calculated from the last 10 requests.
Challenge: Implement a circuit breaker that automatically recovers and sends a notification when a circuit transitions to open state.
@Component
public class AutoRecoveringCircuitBreaker {
private final CircuitBreakerRegistry registry;
private final NotificationService notifications;
public AutoRecoveringCircuitBreaker(
CircuitBreakerRegistry registry,
NotificationService notifications) {
this.registry = registry;
this.notifications = notifications;
registerListeners();
}
private void registerListeners() {
registry.getAllCircuitBreakers().forEach(cb -> {
cb.getEventPublisher()
.onStateTransition(event -> {
if (event.getStateTransition().getToState() == CircuitBreaker.State.OPEN) {
notifications.alert("Circuit opened: " + cb.getName());
}
if (event.getStateTransition().getToState() == CircuitBreaker.State.CLOSED) {
notifications.info("Circuit recovered: " + cb.getName());
}
});
});
}
}
FAQ
Mini Project
Build a Spring Boot service with three circuit breakers for different downstream services (signature database, file storage, notification service), each with its own configuration, fallback, and monitoring endpoint.
@SpringBootApplication
@EnableCircuitBreaker
public class ScanningServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ScanningServiceApplication.class, args);
}
@Bean
public CommandLineRunner demo(CircuitBreakerRegistry registry) {
return args -> {
registry.getAllCircuitBreakers().forEach(cb -> {
System.out.println("Circuit: " + cb.getName()
+ " Config: window=" + cb.getCircuitBreakerConfig().getSlidingWindowSize()
+ " threshold=" + cb.getCircuitBreakerConfig().getFailureRateThreshold() + "%");
});
};
}
}
What's Next
Now that you understand Spring Boot circuit breakers, build the complete circuit breaker project that combines everything you've learned into a production-ready implementation.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro