Retry patterns: when you should give up (and why most code doesn't)
Originally published on Loop & Retry — field notes on building LLM agents that survive production. The retry-budget post answered the HOW: a shared bucket that caps retries as a fraction of throughput. This post answers the WHEN: when should a call fail immediately instead of burning that budget? The answer depends on what fails , who's waiting , and what happens next . It's the decision layer on…
Determining when to fail immediately instead of burning retry budget depends on factors like what is failing, who is waiting, and what happens next. Most code doesn't ask these questions, and instead retries by default. This leads to user-facing calls becoming the customers' timeouts, which can cascade into a platform-wide issue.
For user-facing operations, the cost of one retry attempt is the seconds added to the response time, while the cost of failing now is the user abandonment rate multiplied by lost engagement time and revenue per engagement. In practice, a 30-second timeout with two quick retries is often faster than a lengthy retry-heavy process.
Fail fast on user-facing operations unless the error is known-transient and very rare. Background jobs have more leeway to wait, but should still retry longer than user-facing code without going overboard. Cascade failures happen when multiple requests to a downstream service start retrying simultaneously due to a service hiccup.
To prevent this, shared retry budgets, circuit breakers, decorrelated jitter, and dead-letter quarantine are important.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.