💻
Code Snippet — August 5, 2026JavaScript: Retry with Exponential Backoff, Jitter & Circuit BreakerZero-dependency
retry() that handles transient errors properly:
function retry(fn, {attempts=3, baseDelay=1000, maxDelay=30000, strategy="jitter", shouldRetry=()=>true, circuitBreaker:cb}= {}) {
if(cb){cb.threshold??=5;cb.cooldownMs??=10000;cb.state??="closed";cb.failures??=0}
const errors=[];
async function attempt(){
if(cb?.state==="open"&&Date.now()-cb.lastFailureTime<cb.cooldownMs)
throw new Error("Circuit OPEN");
try{
const r=await fn();
cb&&(cb.failures=0,cb.state==="half-open"&&(cb.state="closed"));
return r;
}catch(e){
errors.push(e);
cb&&(cb.failures++,cb.lastFailureTime=Date.now(),cb.failures>=cb.threshold&&(cb.state="open"));
if(!shouldRetry(e)||errors.length>=attempts)throw e;
const d=strategy==="jitter"?Math.random()*baseDelay*2**errors.length:baseDelay*2**errors.length;
await new Promise(r=>setTimeout(r,Math.min(d,maxDelay)));
return attempt();
}
}
return attempt();
}
Usage:retry(async()=>fetch('/api'),{
attempts:3, strategy:"jitter",
shouldRetry:e=>e.status>=500||e.status===429
});
Features: Jitter (prevents thundering herd), circuit breaker (open→half-open→closed), custom retry predicate, per-attempt timeout. Works in Node, browsers, Deno, Bun.
💡
Drop in utils/retry.js — never write retry logic inline again.