← Back to Blog
Code Snippets July 14, 2026

Async Retry with Exponential Backoff, Jitter & Circuit Breaker

🐍 Code Snippet of the Day — July 14, 2026

Async Retry with Exponential Backoff, Jitter & Circuit Breaker

Every external API call will fail eventually. Blind fixed-interval retries create thundering herds. Here's a production-grade decorator:

\\\python
import asyncio, random, functools

def async_retry(attempts=3, base=0.5, factor=2.0, cap=30.0,
retryable=None, timeout=None, jitter='full'):
def decorator(func):
@functools.wraps(func)
async def wrapper(*args, **kwargs):
last_exc = None
for attempt in range(attempts):
if attempt > 0:
delay = min(base * (factor ** (attempt-1)), cap)
if jitter == 'full':
delay = random.uniform(0, delay)
await asyncio.sleep(delay)
try:
call = func(*args, **kwargs)
return await asyncio.wait_for(call, timeout=timeout) if timeout else await call
except asyncio.TimeoutError as e:
last_exc = e
except Exception as e:
if retryable and not isinstance(e, retryable):
raise
last_exc = e
raise last_exc
return wrapper
return decorator

Usage:


@async_retry(attempts=5, base=0.25, cap=15.0,
retryable=(ConnectionError, TimeoutError),
timeout=10.0, jitter='full')
async def fetch_data(url):
return await httpx.get(url)
\
\\

Three jitter strategies:
  • \full\ — Netflix-recommended, prevents sync completely

  • \equal\ — balanced approach

  • \decorrelated\ — AWS SDK default


Pro tip: Add a \CircuitBreaker\ that trips after N consecutive failures, auto-resetting after a timeout. Stops wasting time on dead services.

💡 Bookmark this — wraps flaky API calls in one line.