Circuit Breaker

Protects the system from cascading failures by cutting off calls to a struggling service.

Context

A dependency (external API, DB, cache) starts to fail/timeout. Your application keeps calling it, exhausting threads and propagating latency.

Problem
  • Calling something known to be broken wastes resources.
  • Massive retries worsen the incident.
Solution

A breaker monitors failures. If they exceed a threshold, it transitions to Open and immediately rejects calls. After a period, it attempts in Half-Open and decides.

#Example in C# — Polly

using Polly;
using Polly.CircuitBreaker;

var breaker = Policy
    .Handle<HttpRequestException>()
    .CircuitBreakerAsync(
        exceptionsAllowedBeforeBreaking: 5,
        durationOfBreak: TimeSpan.FromSeconds(30),
        onBreak: (ex, ts) => log.LogWarning("Breaker opened {Span}", ts),
        onReset: () => log.LogInformation("Breaker closed"));

var response = await breaker.ExecuteAsync(() => httpClient.GetAsync("/api/orders"));
Tradeoffs
Pro Con
Prevents cascading failures Some requests fail fast even if the service has recovered
Allows remote service time to recover Configuring thresholds requires observability

#Variants

  • Bulkhead (isolates thread pools per dependency).
  • Retry with exponential jitter (often combined with Circuit Breaker).

#extra #resilience