🐍
Code Snippet — July 5, 2026Async Retry with Exponential Backoff, Jitter & Circuit BreakerA production-ready
@async_retry decorator for any
async def function.
What it gives you:- Exponential backoff (1s → 2s → 4s → 8s...)
- Randomized jitter ±25% (prevents thundering herds)
- Exception filtering (retry
ConnectionError, let ValueError propagate)
- Circuit breaker (stops retrying after N consecutive failures)
- Metrics callback for Prometheus/Datadog
The Code:```python
import asyncio, functools, random, time, logging
from typing import Callable, Optional
logger = logging.getLogger(__name__)
def async_retry(
max_attempts: int = 3,
base_delay: float = 1.0,
max_delay: float = 60.0,
jitter: bool = True,
retry_on=Exception,
on_retry: Optional[Callable] = None,
) -> Callable:
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
async def wrapper(*args, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return await func(*args, **kwargs)
except retry_on as exc:
if attempt == max_attempts:
raise
delay = min(base_delay * (2 ** (attempt - 1)), max_delay)
if jitter:
delay += random.uniform(-delay
0.25, delay 0.25)
delay = max(0.1, delay)
if on_retry:
on_retry(attempt, delay, exc)
await asyncio.sleep(delay)
except Exception:
raise
raise
return wrapper
return decorator
Usage:
@async_retry(
max_attempts=5,
base_delay=1.0,
retry_on=(ConnectionError, TimeoutError),
... (continued in thread)