🐍
Code Snippet of the Day — July 14, 2026Async Retry with Exponential Backoff, Jitter & Circuit BreakerEvery 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.