In a microservices architecture, service-to-service communication is common. However, it introduces the risk of cascading failures when one service goes down. To address this, we use Resilience4j, a lightweight fault tolerance library inspired by Netflix Hystrix.
In this post, we’ll explore:
- What is a Circuit Breaker?
- Introduction to Resilience4j
- Integrating Resilience4j Circuit Breaker in Spring Boot
- Fallbacks, Retry, and Rate Limiter
- Configuration and Monitoring

π§© What is a Circuit Breaker?
A Circuit Breaker is a design pattern used to detect failures and encapsulate the logic of preventing a failure from constantly recurring during maintenance, outages, or system overloads.
Circuit Breaker States:
- Closed: Requests flow normally.
- Open: All requests are blocked immediately.
- Half-Open: Some requests are allowed to test if the service has recovered.
When failures exceed a threshold, the breaker “opens” to prevent further damage.
π What is Resilience4j?
Resilience4j is a fault tolerance library built for Java 8+ and functional programming. It provides:
- CircuitBreaker
- Retry
- RateLimiter
- TimeLimiter
- Bulkhead
- Cache
Lightweight and easy to integrate with Spring Boot.
βοΈ Add Resilience4j to Your Project
Maven Dependency
1 2 3 4 5 6 7 |
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot3</artifactId> </dependency> |
Add Spring Boot Starter Web
1 2 3 4 5 6 7 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> |
ποΈ Project Structure
1 2 3 4 5 6 7 8 9 10 11 12 |
com.kscodes.springboot.microservice β βββ controller β βββ ProductController.java βββ service β βββ ProductService.java βββ exception β βββ FallbackHandler.java βββ Application.java |
π₯οΈ Service with Circuit Breaker
β
ProductService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.kscodes.springboot.microservice.service; import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker; import org.springframework.stereotype.Service; import java.util.Random; @Service public class ProductService { @CircuitBreaker(name = "productServiceCB", fallbackMethod = "fallbackForProduct") public String getProductInfo(String productId) { if (new Random().nextBoolean()) { throw new RuntimeException("Simulated service failure"); } return "Product Info for ID: " + productId; } public String fallbackForProduct(String productId, Throwable throwable) { return "Fallback: Product service is currently unavailable. Please try later."; } } |
β
ProductController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.kscodes.springboot.microservice.controller; import com.kscodes.springboot.microservice.service.ProductService; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/products") public class ProductController { private final ProductService productService; public ProductController(ProductService productService) { this.productService = productService; } @GetMapping("/{id}") public String getProduct(@PathVariable String id) { return productService.getProductInfo(id); } } |
βοΈ Resilience4j Configuration in application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
resilience4j: circuitbreaker: instances: productServiceCB: registerHealthIndicator: true slidingWindowSize: 5 failureRateThreshold: 50 minimumNumberOfCalls: 5 waitDurationInOpenState: 10s permittedNumberOfCallsInHalfOpenState: 2 automaticTransitionFromOpenToHalfOpenEnabled: true management: endpoints: web: exposure: include: "*" |
π§ͺ Test the Circuit Breaker
Send multiple requests to /api/products/123
and observe the fallback behavior after simulated failures. You can test using curl
or Postman.
π Adding Retry (Optional)
1 2 3 4 5 6 7 8 9 |
resilience4j: retry: instances: productServiceCB: maxAttempts: 3 waitDuration: 500ms |
1 2 3 4 |
@Retry(name = "productServiceCB", fallbackMethod = "fallbackForProduct") |
π Monitoring with Actuator and Health Checks
Add the following dependency:
1 2 3 4 5 6 7 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> |
Visit
1 2 3 4 5 |
http://localhost:8080/actuator/health http://localhost:8080/actuator/circuitbreakerevents |
π¦ Sample Response
1 2 3 4 |
Fallback: Product service is currently unavailable. Please try later. |
π§ Key Takeaways
- Circuit Breaker prevents resource exhaustion and cascading failures.
- Resilience4j offers simple annotations to integrate robust fault tolerance.
- Use fallback methods to provide better UX during downtimes.
- Combine CircuitBreaker with Retry and RateLimiter for resilient APIs.
π Conclusion
Using Resilience4j Circuit Breaker in Spring Boot enhances the resilience and stability of your microservices. It’s lightweight, easy to configure, and designed for Java functional programming.
β Donβt forget to monitor your breakers and fine-tune thresholds as your system evolves.