Contents

Circuit Breaker Pattern

Circuit Breaker Pattern

It prevents cascading failures by stopping calls to a failing service once errors cross a threshold. It provides fallback mechanisms to keep the system stable even when dependencies fail like a safety switch.

Example: Suppose your online store depends on a payment service. If that service starts failing repeatedly, the circuit breaker “trips” and stops further calls for a while, preventing cascades and giving the service time to recover.

Characteristics

  • Improves fault tolerance by isolating failing dependencies.
  • Monitors latency, error rate, and timeouts over a rolling window.
  • Prevents cascades by temporarily stopping calls to an unhealthy service.
  • Supports fallbacks (default responses, cached data, queueing) for graceful degradation.
  • Auto-recovers by probing and resetting when the service stabilizes.

Different states:

  • Closed State
    • In the Closed state, the circuit breaker operates normally, allowing requests to flow through between services.
  • Open State
    • When the monitored metrics breach predetermined thresholds, signaling potential issues with the downstream service, the circuit breaker transitions to the Open state.
    • In the Open state, the circuit breaker immediately stops forwarding requests to the failing service, effectively isolating it.
  • Half-Open State
    • After a specified timeout period in the Open state, transitions to Half-Open state.
    • Allows a limited number of trial requests to pass through to the downstream service.
    • Monitors responses to determine service recovery.
    • If trial requests succeed, indicating service recovery, transitions back to Closed state.
    • If trial requests fail, service issues persist.
    • May transition back to Open state or remain in Half-Open state for further evaluation.

Libraries for implementation: Resilience4j, Spring Cloud Circuit Breaker, Hystrix (in maintenance mode)

Example in a Spring boot application

Maven dependency (pom.xml)

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot3</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Configuration (application.yaml)

resilience4j:
  circuitbreaker:
    instances:
      userService:
        registerHealthIndicator: true
        slidingWindowSize: 10
        minimumNumberOfCalls: 5
        failureRateThreshold: 50
        waitDurationInOpenState: 10s
        permittedNumberOfCallsInHalfOpenState: 3
        slidingWindowType: COUNT_BASED

Usage

@Service
public class UserService {

    private final RestTemplate restTemplate;

    public UserService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    // name must match the instance name in application.yml
    @CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
    public String getUserData(String userId) {
        return restTemplate.getForObject("http://external-service/users/" + userId, String.class);
    }

    // Fallback must have the same signature + Throwable
    public String getUserFallback(String userId, Throwable t) {
        return "Fallback response: Service is currently unavailable.";
    }
}