Retry With Exponential Backoff and Jitter (JavaScript)

Retry a flaky async operation a bounded number of times, doubling the delay between attempts, adding jitter, and only retrying errors that are safe to repeat.

JavascriptResilience

Code

snippet
export async function retry(fn, options = {}) {
  const maxAttempts = options.maxAttempts ?? 5;
  const baseDelayMs = options.baseDelayMs ?? 100;
  for (let attempt = 1; ; attempt++) {
    try {
      return await fn(attempt);
    } catch (error) {
      if (attempt >= maxAttempts || !isRetryable(error)) throw error;
      const jitter = Math.random() * baseDelayMs;
      const delay = baseDelayMs * 2 ** (attempt - 1) + jitter;
      await sleep(delay);
    }
  }
}

function isRetryable(error) {
  if (!error || typeof error !== "object") return false;
  const status = error.status ?? error.statusCode;
  return status === undefined || status >= 500 || status === 429;
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}