Home/Learn/Microservices/Circuit Breaker Pattern

Circuit Breaker Pattern

Intermediate
Resilience

When failure rate exceeds a threshold the circuit "opens", short-circuiting calls and returning a fallback; after a wait it goes half-open to probe recovery.

Overview

The Circuit Breaker pattern prevents a service from repeatedly hammering a downstream dependency that is failing or slow — a behaviour that wastes threads, causes latency spikes, and can cascade into a full system outage. Named after an electrical circuit breaker, it wraps outbound calls and transitions through three states: CLOSED (normal, requests flow through), OPEN (failing, requests are short-circuited to a fallback immediately), and HALF-OPEN (recovering, a limited probe is sent to test whether the downstream service has recovered). The pattern was popularised by Netflix's Hystrix library; today Resilience4j is the standard choice in the Spring Boot ecosystem. A circuit breaker is one of the most important resilience patterns in any microservices architecture.

Three States of a Circuit Breaker

CLOSED (normal operation): Calls pass through to the downstream service. Failures are counted in a sliding window (count-based or time-based). When the failure rate exceeds the configured threshold (e.g., 50% of the last 10 calls), the circuit transitions to OPEN.

OPEN (fast fail): All calls are immediately rejected without attempting the downstream call. A fallback method (cached result, default value, or error response) is returned to the caller. The circuit stays open for a configurable waitDurationInOpenState (e.g., 30 seconds).

HALF-OPEN (recovery probe): After the wait, a limited number of test calls are allowed through. If they succeed, the circuit closes again. If they fail, the circuit re-opens and waits again.

application.yml
// Resilience4j Circuit Breaker — configuration
resilience4j:
  circuitbreaker:
    instances:
      paymentService:
        slidingWindowType: COUNT_BASED
        slidingWindowSize: 10            # evaluate last 10 calls
        failureRateThreshold: 50         # open if >=50% fail
        waitDurationInOpenState: 30s     # stay open for 30 seconds
        permittedNumberOfCallsInHalfOpenState: 3
        recordExceptions:
          - java.io.IOException
          - java.util.concurrent.TimeoutException

Using @CircuitBreaker with Spring Boot

Add spring-boot-starter-aop and resilience4j-spring-boot3 to your project. Annotate the method that calls the downstream service with @CircuitBreaker and provide a fallback method. The fallback must have the same return type and an additional Throwable parameter.

Java — Spring Boot + Resilience4j
@Service
@RequiredArgsConstructor
public class OrderService {

    private final PaymentClient paymentClient;

    @CircuitBreaker(name = "paymentService", fallbackMethod = "paymentFallback")
    public PaymentResponse processPayment(PaymentRequest request) {
        // This call is wrapped — if it fails repeatedly, circuit opens
        return paymentClient.charge(request);
    }

    // Fallback — same return type + Throwable parameter
    private PaymentResponse paymentFallback(PaymentRequest request, Throwable ex) {
        log.warn("Payment service circuit open, using fallback. Cause: {}", ex.getMessage());
        return PaymentResponse.builder()
            .status("PENDING")
            .message("Payment queued — service temporarily unavailable")
            .build();
    }
}

Monitoring Circuit Breaker State

Resilience4j integrates with Spring Boot Actuator and Micrometer. Circuit breaker state transitions are exposed as metrics (resilience4j.circuitbreaker.state) and can be visualised in Grafana dashboards. Always alert on STATE_OPEN transitions — an open circuit means a dependency is down.

Java — Spring Boot Actuator
// Check circuit breaker state programmatically
@RestController
@RequiredArgsConstructor
public class HealthController {

    private final CircuitBreakerRegistry registry;

    @GetMapping("/cb-state")
    public Map<String, String> circuitState() {
        return registry.getAllCircuitBreakers().stream()
            .collect(Collectors.toMap(
                CircuitBreaker::getName,
                cb -> cb.getState().name()   // CLOSED, OPEN, or HALF_OPEN
            ));
    }
}

// Expose via Actuator (application.properties)
management.endpoints.web.exposure.include=health,metrics
management.health.circuitbreakers.enabled=true

Key Points to Remember

  • 1Circuit breaker has three states: CLOSED (normal), OPEN (fast-fail), HALF-OPEN (recovery probe).
  • 2The circuit opens when the failure rate in a sliding window (count or time-based) exceeds the configured threshold.
  • 3Always provide a fallback method — a cached response, a default value, or a graceful error — so the caller never waits for a timeout.
  • 4waitDurationInOpenState prevents hammering a recovering service; set it to at least the expected recovery time of the downstream service.
  • 5Circuit breakers prevent cascading failures: an open circuit stops thread exhaustion in the upstream service.
  • 6Combine with Retry (for transient failures) and Bulkhead (for resource isolation) to build a comprehensive resilience strategy.

Interview Questions

Sign in to ask Aria
1

Explain the three states of a circuit breaker and the transitions between them.

MediumAmazon
2

How is a circuit breaker different from a retry pattern? When would you use each?

MediumUber
3

What happens to user requests when the circuit breaker is in OPEN state?

EasyFlipkart
4

How do you implement a circuit breaker in Spring Boot with Resilience4j?

MediumNetflix
5

A downstream service is slow (not failing). How do you make a circuit breaker react to slowness?

HardGoogle

Ask Aria about Circuit Breaker Pattern

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…