Sikau

System design · Day 7 · about 35 min

Circuit breakers

Stop calling a failing service; probe it again after a cooldown.

Failing fast

When a dependency is down, waiting for each request to time out ties up your threads and spreads the outage. A circuit breaker counts failures; after too many it opens and rejects calls instantly. After a cooldown it goes half-open and lets one trial call through: success closes it, failure opens it again.

Three states

function createBreaker(fn, { threshold = 3, cooldown = 1000, now = () => Date.now() } = {}) {
  let state = "closed";
  let failures = 0;
  let openedAt = 0;
  return {
    async call(...args) {
      if (state === "open") {
        if (now() - openedAt < cooldown) throw new Error("Circuit open"); // fail fast
        state = "half-open"; // let one trial request through
      }
      try {
        const value = await fn(...args);
        state = "closed";
        failures = 0;
        return value;
      } catch (e) {
        failures++;
        if (state === "half-open" || failures >= threshold) {
          state = "open";
          openedAt = now();
        }
        throw e;
      }
    },
    state: () => state,
  };
}

The rest of this lesson

  • How outages spreadexplain
  • Fallbacksexplain
  • A breaker's lifeorder
  • Breaker statematch
  • Build a breakerwrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 8 lessons of System design