Circuit Breaker Pattern in Microservices using Spring Boot 3, WebClient and Resilience4j

🚀 Introduction: Why Circuit Breaker Matters in Microservices?

In microservices architecture, failures in one service can impact multiple services. Common issues include:
Network failures
Service timeouts
Slow response times

Without proper handling, these failures can lead to:
Increased latency
System-wide slowdowns
Cascading failures across microservices

✅ Solution: The Circuit Breaker Pattern

The Circuit Breaker Pattern helps by:
1️⃣ Detecting service failures
2️⃣ Preventing unnecessary calls to failing services
3️⃣ Returning a fallback response instead of failing entirely
4️⃣ Automatically retrying after a cooldown period

1️⃣ Architecture of Our Microservices Example

We will build two microservices and implement the Circuit Breaker pattern using Spring Boot 3+, WebClient, and Resilience4j.

Microservices Involved:

Order Service (order-service) → Calls Payment Service
Payment Service (payment-service) → Fails randomly to simulate failures

📌 If payment-service fails, order-service should handle the failure gracefully using the Circuit Breaker.

2️⃣ Payment Service (Simulating Failures)

Step 1: Create payment-service

@RestController
@RequestMapping("/api/payments")
public class PaymentController {

    @GetMapping("/{orderId}")
    public ResponseEntity<String> processPayment(@PathVariable String orderId) {
        // Simulating service failure randomly
        if (new Random().nextInt(10) < 4) { // 40% failure rate
            throw new RuntimeException("Payment Service is Down!");
        }
        return ResponseEntity.ok("Payment successful for Order ID: " + orderId);
    }
}

📌 This service randomly fails 40% of the time to test Circuit Breaker behavior.

3️⃣ Order Service with Circuit Breaker (Spring Boot 3+)

Step 1: Add Dependencies (Spring Boot 3+ & Resilience4j)

Update pom.xml to use the latest Resilience4j dependency for Spring Boot 3+:

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot3</artifactId>
</dependency>

WebClient is used instead of RestTemplate because RestTemplate is deprecated in Spring Boot 3+.

Step 2: Configure WebClient in OrderService

@Configuration
public class WebClientConfig {
    @Bean
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

📌 This config allows us to use WebClient for making HTTP calls.

Step 3: Implement Circuit Breaker in Order Service

@Service
public class OrderService {

    private final WebClient.Builder webClientBuilder;

    public OrderService(WebClient.Builder webClientBuilder) {
        this.webClientBuilder = webClientBuilder;
    }

    @CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPayment")
    public String placeOrder(String orderId) {
        return webClientBuilder.build()
                .get()
                .uri("http://localhost:8081/api/payments/" + orderId) // Call Payment Service
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }

    public String fallbackPayment(String orderId, Throwable t) {
        return "Fallback: Payment service is currently unavailable. Placing order without payment confirmation.";
    }
}

📌 If the payment-service is down, the fallbackPayment() method is triggered instead.

Step 4: Create Order Controller

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    @PostMapping("/{orderId}")
    public ResponseEntity<String> createOrder(@PathVariable String orderId) {
        return ResponseEntity.ok(orderService.placeOrder(orderId));
    }
}

This API will attempt to process a payment and place an order.

4️⃣ Configuring Circuit Breaker Properties

Add the following properties in application.yml for Circuit Breaker behavior tuning:

resilience4j:
  circuitbreaker:
    instances:
      paymentService:
        failureRateThreshold: 50 # Opens when 50% of calls fail
        slowCallRateThreshold: 50
        slowCallDurationThreshold: 2000ms # 2 seconds
        permittedNumberOfCallsInHalfOpenState: 2
        waitDurationInOpenState: 5000ms # 5 seconds
        slidingWindowSize: 10
        minimumNumberOfCalls: 5

📌 This configuration ensures that the circuit breaker opens if 50% of calls fail within 10 attempts.

5️⃣ Testing Circuit Breaker Using Postman

1️⃣ Case: Payment Service is Available

📌 Request:

POST http://localhost:8080/api/orders/123

📌 Response:

{
  "message": "Payment successful for Order ID: 123"
}

Everything works fine if the payment service is available.

2️⃣ Case: Payment Service Fails (Circuit Breaker Activated)

📌 Request:

POST http://localhost:8080/api/orders/456

📌 Response (Fallback Triggered):

{
  "message": "Fallback: Payment service is currently unavailable. Placing order without payment confirmation."
}

Instead of failing, the order is placed without payment confirmation.

6️⃣ Benefits of Circuit Breaker in Microservices

Prevents cascading failures when a service goes down
Provides fallback responses to improve user experience
Automatically recovers after a cooldown period
Improves system stability and resilience

7️⃣ Best Practices for Circuit Breaker in Microservices

✔ Set failure thresholds wisely to avoid false positives
✔ Implement fallback methods to ensure graceful degradation
✔ Monitor metrics using Prometheus or Grafana
✔ Combine with Retry Pattern to recover from temporary failures

🎯 Conclusion: Why Circuit Breaker is Essential for Microservices?

By implementing the Circuit Breaker Pattern, you can:
✅ Prevent service failures from cascading across the system
✅ Improve fault tolerance and resilience
✅ Ensure better user experience with fallbacks

🚀 Have you implemented Circuit Breaker in your microservices? Comment below!

🔗 Share this guide with developers to help them build resilient microservices! 🚀

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare