patternjavascriptMajor
Retry Strategies with Fetch: Exponential Backoff and Idempotency Checks
Viewed 0 times
retrybackoffidempotencyfetch429idempotency-keyresilience
Error Messages
Problem
Applications retry failed requests including POST/PATCH requests that may have partially succeeded server-side, causing duplicate operations (double charges, duplicate records).
Solution
Only automatically retry idempotent requests (GET, PUT, DELETE) or requests with a server-recognized idempotency key. Use exponential backoff.
async function fetchWithRetry(url, options = {}, retries = 3) {
const idempotent = ['GET', 'HEAD', 'PUT', 'DELETE'].includes(
(options.method || 'GET').toUpperCase()
);
for (let attempt = 0; attempt <= retries; attempt++) {
try {
const res = await fetch(url, options);
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get('Retry-After') || '1', 10);
await delay(retryAfter * 1000);
continue;
}
if (res.status >= 500 && idempotent && attempt < retries) {
await delay(Math.min(1000 * 2 ** attempt, 30000));
continue;
}
return res;
} catch (err) {
if (attempt === retries || !idempotent) throw err;
await delay(Math.min(1000 * 2 ** attempt, 30000));
}
}
}
const delay = (ms) => new Promise(r => setTimeout(r, ms));Why
Retrying POST without idempotency keys can cause financial or data integrity issues. The RFC recommends using Idempotency-Key headers (stripe's pattern) for POST requests that must be retried safely.
Gotchas
- Network errors (TypeError from fetch) can occur after the request was received and processed by the server.
- Use an Idempotency-Key header (UUID) for POST retries on payment or order endpoints.
- Jitter should be added to backoff when many clients may be retrying simultaneously.
Revisions (0)
No revisions yet.