Headline: Naive retries turn a slow dependency into a self-inflicted outage, because every caller retrying on the same schedule multiplies load on a service that is already failing. The combination that works is a hard per-attempt timeout, exponential backoff with full jitter under a total retry budget, an Idempotency-Key header on every non-idempotent write, and a circuit breaker that stops calling a dependency that is already down.
A background worker I maintain calls a third-party payments API. During a partial outage on their side, requests started taking 30 seconds and then failing. My retry wrapper did exactly what I had told it to do: try again immediately, three times. Throughput collapsed, the queue backed up, and when the dependency started recovering my workers were still hammering it in lockstep. The retries were not helping the recovery; they were part of what was preventing it. These are my notes from rebuilding that call path.
Key takeaways
Retry amplification is real arithmetic.…