TypeScript

Retry with Exponential Backoff + Jitter

admin by @admin ADMIN
5d ago
May 31, 2026
Public
0 0 up · 0 down Sign in to vote
Retry an async operation up to N times, doubling the delay each attempt with random jitter to avoid thundering herd. Decide retryability via an optional predicate so 4xx errors stop immediately.
TypeScript
Raw
type RetryOpts = {
  attempts?: number;
  baseMs?: number;
  shouldRetry?: (err: unknown, attempt: number) => boolean;
};

export async function retry<T>(fn: () => Promise<T>, opts: RetryOpts = {}): Promise<T> {
  const attempts = opts.attempts ?? 5;
  const baseMs   = opts.baseMs   ?? 200;
  const should   = opts.shouldRetry ?? (() => true);

  let lastErr: unknown;
  for (let i = 1; i <= attempts; i++) {
    try { return await fn(); }
    catch (e) {
      lastErr = e;
      if (i === attempts || !should(e, i)) throw e;
      const delay = baseMs * 2 ** (i - 1);
      const jitter = Math.random() * delay;
      await new Promise(r => setTimeout(r, delay + jitter));
    }
  }
  throw lastErr;   // unreachable, but TS wants it
}

const data = await retry(() => fetch('/api').then(r => r.json()), {
  attempts: 4,
  shouldRetry: (e) => !(e instanceof Response) || e.status >= 500,
});
Tags

Save your own code snippets

Create a free account and build your private vault. Share publicly whenever you want.