When a service experiences transient outages or load spikes, naive retries immediately trigger cascading failures.
1. Exponential Backoff
Increase wait times exponentially between successive retries: delay = min(base * (2 ^ attempt), max_delay)
2. Adding Jitter (Random Noise)
If 5,000 requests fail simultaneously (e.g. network blip), exponential backoff will still cause all 5,000 clients to retry at the exact same millisecond. Adding Full Jitter randomizes retry times: delay_with_jitter = random(0, delay)
import random
import time
def call_with_retry(api_func, max_attempts=5):
for attempt in range(max_attempts):
try:
return api_func()
except Exception as e:
if attempt == max_attempts - 1:
raise e
backoff = min(30, 0.5 * (2 ** attempt))
jittered_delay = random.uniform(0, backoff)
time.sleep(jittered_delay)AWS benchmarks prove that applying Full Jitter flattens server load recovery spikes into smooth, manageable traffic curves.
Key Architectural Comparison
| Retry Strategy | Formula / Backoff Delay | Stampede Prevention | Server Protection |
|---|---|---|---|
| Fixed Interval | $\Delta t = C$ | None (Workers synchronize, repeatedly hammering server). | Dangerous. |
| Exponential Backoff | $\Delta t = B \times 2^{\text{attempt}}$ | Low (Workers space out over time, but stay in sync). | Moderate. |
| Exponential Backoff + Full Jitter | $\Delta t = \text{random}(0, B \times 2^{\text{attempt}})$ | Maximum (Spreads worker retries uniformly across timeline). | AWS Best Practice. |