Circuit Breakers and Retry Logic
May 30, 2026 | 5 min read
Circuit Breaker Pattern
class CircuitBreaker:
def __init__(self, threshold: int = 5, timeout: float = 60.0):
self.threshold = threshold
self.timeout = timeout
self.failures = 0
self.last_failure = 0.0
self.state = 'closed'
def call(self, fn, *args, **kwargs):
if self.state == 'open':
if time.time() - self.last_failure > self.timeout:
self.state = 'half_open'
else:
raise Exception('circuit open')
try:
result = fn(*args, **kwargs)
self._on_success()
return result
except Exception as e:
self._on_failure()
raise e
def _on_success(self):
self.failures = 0
self.state = 'closed'
def _on_failure(self):
self.failures += 1
self.last_failure = time.time()
if self.failures >= self.threshold:
self.state = 'open'
Exponential Backoff Retry
import time
import random
def retry_with_backoff(fn, max_retries=5):
for attempt in range(max_retries):
try:
return fn()
except Exception:
if attempt == max_retries - 1:
raise
sleep = (2 ** attempt) + random.random()
time.sleep(sleep)