Course contentsShow
← Rust
Lesson 889 of 1,9107. Error Handling PatternsFree lesson

Circuit Breaker Pattern in Rust

Design stateful error-aware components that stop execution during repeated failures.

In this lesson, you will learn how to implement the Circuit Breaker pattern to protect your system from cascading failures by automatically halting requests to a service that is consistently erroring.

The Logic of the Breaker

Imagine your application is calling a remote database that is currently failing. If you keep retrying every request, you waste CPU cycles and potentially overwhelm the service further. A Circuit Breaker acts as a state machine with three modes:

  1. Closed: Requests flow normally. Failures are tracked.
  2. Open: Requests are blocked immediately. The system is "tripped," allowing the downstream service to recover.
  3. Half-Open: A limited number of test requests are allowed. If they succeed, the breaker resets to Closed.

Implementation Pattern

In Rust, we typically model this using an enum for the state and a struct to track failure counts. Because this component is stateful and often shared across threads, you will frequently wrap it in an Arc<Mutex<T>>.

enum State { Closed, Open(Instant), HalfOpen }

struct CircuitBreaker {
    state: State,
    failure_count: u32,
    threshold: u32,
}

impl CircuitBreaker {
    fn call<F, T, E>(&mut self, action: F) -> Result<T, E> 
    where F: FnOnce() -> Result<T, E> 
    {
        if let State::Open(until) = self.state {
            if Instant::now() < until {
                return Err(CustomError::CircuitOpen);
            }
            self.state = State::HalfOpen;
        }

        match action() {
            Ok(val) => {
                self.failure_count = 0;
                self.state = State::Closed;
                Ok(val)
            }
            Err(e) => {
                self.failure_count += 1;
                if self.failure_count >= self.threshold {
                    self.state = State::Open(Instant::now() + Duration::from_secs(30));
                }
                Err(e)
            }
        }
    }
}

By decoupling the execution logic from the state tracking, the circuit breaker allows your application to "fail fast" when it knows a downstream dependency is unhealthy. This pattern is essential for building distributed systems that respect the stability of the services they rely on.

Key Takeaway: The Circuit Breaker prevents resource exhaustion by switching from active execution to a fail-fast state once a failure threshold is reached.