exponentialBackoff
Retry with exponentially growing delays, capped at an upper bound.
exponentialBackoff(...) creates a policy that doubles the delay after each failure, up to a hard cap, reducing pressure on unstable upstream services.
Import
import { exponentialBackoff } from "@zap-studio/retry";
Configuration
import { exponentialBackoff } from "@zap-studio/retry";
const policy = exponentialBackoff({
maxAttempts: 6,
baseDelayMs: 100,
maxDelayMs: 5_000,
});
| Option | Type | Default | Description |
|---|---|---|---|
maxAttempts |
number |
— | Maximum number of attempts (including the first) before giving up. |
baseDelayMs |
number |
— | Initial delay in milliseconds, doubled after each retry. |
maxDelayMs |
number |
— | Hard upper bound in milliseconds for the computed delay. |
jitter |
"full" | "equal" | JitterOptions |
— | Randomizes the capped delay. See Jitter. |
All options are required except jitter.
Delay Model
The delay before the next retry is computed from the failed attempt number:
delayMs = Math.min(maxDelayMs, baseDelayMs * 2 ** (attempt - 1));
With baseDelayMs: 100 and maxDelayMs: 2_000:
- after attempt 1 → wait
100ms - after attempt 2 → wait
200ms - after attempt 3 → wait
400ms - after attempt 4 → wait
800ms - after attempt 5 → wait
1_600ms - after attempt 6 → wait
2_000ms (capped)
The policy stops retrying when attempt >= maxAttempts, returning a decision with reason: "max-attempts-reached".
When to Use
Use exponentialBackoff when:
- retries target shared or networked services
- transient failures are common
- aggressive immediate retries could amplify outages
For predictable, constant intervals, use fixedDelay instead.
Example
import { exponentialBackoff, runRetryPolicy } from "@zap-studio/retry";
import { $fetch } from "@zap-studio/fetch";
const policy = exponentialBackoff({
maxAttempts: 5,
baseDelayMs: 100,
maxDelayMs: 2_000,
});
const user = await runRetryPolicy(policy, async () => {
const response = await $fetch("https://api.example.com/users/1", {
throwOnFetchError: true,
});
return await response.json();
});