How to implement retry logic with async operations
· Category: Node.js
Short answer
Wrap your async operation in a loop that catches errors, waits using an exponential backoff delay, and retries up to a maximum number of attempts.
Steps
- Create an async function that accepts the operation, max retries, and delay.
- Loop from 0 to max retries.
- Inside the loop, try to execute the operation.
- On failure, wait with
await new Promise(r => setTimeout(r, delay));. - Increase the delay exponentially and throw if the final attempt fails.
async function retry(fn, maxAttempts = 3, delay = 1000) {
for (let i = 0; i < maxAttempts; i++) {
try {
return await fn();
} catch (err) {
if (i === maxAttempts - 1) throw err;
await new Promise(r => setTimeout(r, delay * Math.pow(2, i)));
}
}
}
Tips
- Use a jitter randomization to prevent thundering herd problems when many clients retry simultaneously.
- Only retry idempotent operations like GET requests, not POST requests that mutate state.
Common issues
- Not capping the maximum delay can lead to unacceptably long waits.
- Retrying on non-transient errors like 400 Bad Request wastes resources.