back
typescript·utilities

Fetch with Exponential Backoff Retry

Reliable fetch wrapper that retries on network errors and 5xx responses with exponential backoff.

#typescript#api#network#utility

typescript
interface FetchOptions extends RequestInit {
  retries?: number;
  backoff?: number; // base delay in ms
}

export async function fetchWithRetry(
  url: string,
  options: FetchOptions = {}
): Promise<Response> {
  const { retries = 3, backoff = 300, ...fetchOptions } = options;

  for (let attempt = 0; attempt <= retries; attempt++) {
    try {
      const res = await fetch(url, fetchOptions);

      // Don't retry client errors (4xx), only server errors (5xx)
      if (res.ok || (res.status >= 400 && res.status < 500)) {
        return res;
      }

      if (attempt === retries) return res;
    } catch (err) {
      if (attempt === retries) throw err;
    }

    // Exponential backoff: 300ms, 600ms, 1200ms ...
    const delay = backoff * 2 ** attempt;
    await new Promise((resolve) => setTimeout(resolve, delay));
  }

  throw new Error('fetchWithRetry: exhausted retries');
}

more snippets