Build a Circuit Breaker

Difficulty: Medium · Category: Circuit Breaker · Languages: Java 17, Python 3.11, Go 1.22, Node.js 20, TypeScript 5.x

Circuit Breaker

Background

In distributed systems a single failing downstream service can bring down the entire call chain. A circuit breaker sits between a caller and a service, monitoring failures. When failures exceed a threshold the breaker "trips" — subsequent calls fail immediately instead of waiting for a timeout, giving the downstream service time to recover.

The pattern is modelled after electrical circuit breakers and has three states: CLOSED (normal), OPEN (tripped), and HALF_OPEN (recovery probe).

Your Task

Implement the CircuitBreakerContract interface. Your implementation must:

  1. Persist all state — failure counts, timestamps, and breaker state must be shared across instances.
  2. Track consecutive failures per service identifier.
  3. Transition to OPEN after failureThreshold consecutive failures.
  4. After recoveryTimeoutMs in OPEN, transition to HALF_OPEN and allow up to halfOpenMaxAttempts test calls.
  5. In HALF_OPEN: a success → CLOSED (reset counts); a failure → OPEN (restart the timer).
  6. Be thread-safe: concurrent calls must not corrupt state.

Recommended infrastructure: redis — for shared circuit state across instances.

How It Works

The platform injects your chosen infrastructure SDK(s) via constructor. For example, if you select Redis:

public class MyCircuitBreaker implements CircuitBreakerContract {
    private final RedisClient redis;

    public MyCircuitBreaker(RedisClient redis) {
        this.redis = redis;
    }

    // ... implement methods using redis.get(), redis.set(), etc.
}

See the SDK Docs tab for the full API reference of your chosen system.

Interface

public interface CircuitBreakerContract {
    void configure(int failureThreshold, long recoveryTimeoutMs, int halfOpenMaxAttempts);
    boolean execute(String serviceId, Callable<Boolean> action);
    String getState(String serviceId);
    int getFailureCount(String serviceId);
    long getLastFailureTimestamp(String serviceId);
    void reset(String serviceId);
}

Method Details

MethodDescription
configureSets breaker parameters. Called once before execute.
executeRuns the action through the breaker. Returns true on success, false on failure or rejection.
getStateReturns "CLOSED", "OPEN", or "HALF_OPEN".
getFailureCountReturns the current consecutive failure count.
getLastFailureTimestampEpoch-millis of the last failure, or 0.
resetResets the breaker to CLOSED with zero failures.

Constraints

Examples

configure(3, 5000, 1)       // 3 failures → open, 5 s recovery, 1 test

execute("svc", () -> true)   → true   // CLOSED, success
execute("svc", () -> { throw … })  → false  // failure 1
execute("svc", () -> { throw … })  → false  // failure 2
execute("svc", () -> { throw … })  → false  // failure 3 → OPEN

getState("svc")              → "OPEN"
execute("svc", () -> true)   → false  // rejected — action never called

// … wait 5 seconds …
getState("svc")              → "HALF_OPEN"
execute("svc", () -> true)   → true   // test passes → CLOSED
getState("svc")              → "CLOSED"

Hints

Infrastructure your code runs against

How your solution is graded

Your score combines functional correctness (50%), performance (30%) and code quality (20%).

Practice this problem

Related LLD problems