typescript 51 lines · 8 steps

Retrying HTTP requests with backoff

A generic wrapper that retries failed requests on transient errors using exponential backoff with jitter.

Explained by highlit
1type RetryableRequest<T> = () => Promise<T>;
2 
3interface RetryOptions {
4 maxAttempts?: number;
5 baseDelayMs?: number;
6 retryOnStatus?: number[];
7}
8 
9class HttpError extends Error {
10 constructor(public readonly status: number, message: string) {
11 super(message);
12 this.name = "HttpError";
13 }
14}
15 
16const isHttpError = (err: unknown): err is HttpError =>
17 err instanceof HttpError;
18 
19const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
20 
21export async function withRetry<T>(
22 request: RetryableRequest<T>,
23 options: RetryOptions = {},
24): Promise<T> {
25 const {
26 maxAttempts = 3,
27 baseDelayMs = 200,
28 retryOnStatus = [429, 502, 503, 504],
29 } = options;
30 
31 let lastError: unknown;
32 
33 for (let attempt = 1; attempt <= maxAttempts; attempt++) {
34 try {
35 return await request();
36 } catch (err) {
37 lastError = err;
38 
39 const retryable = isHttpError(err) && retryOnStatus.includes(err.status);
40 if (!retryable || attempt === maxAttempts) {
41 throw err;
42 }
43 
44 const jitter = Math.random() * baseDelayMs;
45 const delay = baseDelayMs * 2 ** (attempt - 1) + jitter;
46 await sleep(delay);
47 }
48 }
49 
50 throw lastError;
51}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Only retry on transient failures — inspect the error type and status before deciding to try again.
  2. 2Exponential backoff with random jitter spreads out retries and avoids synchronized thundering-herd load.
  3. 3A generic wrapper keeps retry logic reusable across any promise-returning request without coupling to a specific client.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Retrying HTTP requests with backoff — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code