A circuit breaker’s "closed" state isn’t about the physical switch; it’s about actively allowing requests to flow.

Let’s watch a circuit breaker in action. Imagine a service, user-service, that depends on order-service. If order-service starts failing, we want user-service to stop bombarding it with requests immediately. This is where a circuit breaker, often implemented using libraries like Resilience4j or Hystrix, comes in.

Here’s a simplified Java example using Resilience4j:

// Configure the circuit breaker
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .failureRateThreshold(50) // 50% failure rate triggers the breaker
    .waitDurationInOpenState(Duration.ofSeconds(5)) // Stay open for 5 seconds
    .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)
    .slidingWindowSize(10) // Look at the last 10 calls
    .build();

CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
CircuitBreaker orderServiceBreaker = circuitBreakerRegistry.circuitBreaker("orderService");

// In your service code:
// Assume this is a method that calls order-service
Supplier<String> decoratedSupplier = CircuitBreaker.decorateSupplier(orderServiceBreaker, () -> callOrderService());

try {
    String result = decoratedSupplier.get();
    System.out.println("Order service call successful: " + result);
} catch (Exception e) {
    System.err.println("Order service call failed: " + e.getMessage());
}

// Example function to simulate calling the order service
private String callOrderService() {
    // Simulate a 70% chance of failure
    if (Math.random() < 0.7) {
        throw new RuntimeException("Order service is unavailable");
    }
    return "Order details";
}

Initially, the circuit breaker is closed. Requests to order-service go through normally. As failures occur, the breaker monitors them. If the failure rate (here, 50% of the last 10 calls) is exceeded, the breaker "trips" and enters the open state.

In the open state, the circuit breaker immediately rejects any new requests to order-service without even attempting to call it. Instead, it throws an exception, typically a CallNotPermittedException. This prevents the failing order-service from being overwhelmed and gives it time to recover, while also preventing the calling service (user-service) from wasting resources on requests that are guaranteed to fail. The breaker stays in this open state for a configured duration, waitDurationInOpenState (5 seconds in our example).

After the waitDurationInOpenState elapses, the circuit breaker transitions to the half-open state. In this state, it allows a limited number of test requests (usually just one) to pass through to the order-service. If these test requests succeed, the breaker assumes order-service has recovered and closes itself, allowing all subsequent requests. However, if any of these test requests fail, the breaker immediately returns to the open state, restarting the timeout period.

The core problem this solves is cascading failures. Without circuit breakers, a single failing downstream service can quickly bring down the entire upstream system as requests pile up, consume resources, and eventually time out, leading to a widespread outage. Circuit breakers act as a protective mechanism, isolating failures and preventing them from spreading.

The most surprising thing about circuit breaker states is that the "half-open" state isn’t just a transition; it’s a critical diagnostic and recovery phase. It’s actively testing the health of the dependent service. If you only had "closed" and "open," the breaker would either be constantly hammering a failing service or stay permanently open, requiring a manual reset. The half-open state provides an automated, albeit limited, way to detect recovery.

The next concept to explore is how to configure the different types of sliding windows (COUNT_BASED vs. TIME_BASED) and their impact on how quickly the circuit breaker reacts to changes in service health.

Want structured learning?

Take the full Circuit-breaker course →