typescriptintermediate
Retry with Exponential Backoff
Retry failed async operations with exponential backoff, jitter, and configurable retry conditions.
typescriptPress ⌘/Ctrl + Shift + C to copy
interface RetryOptions {
maxAttempts: number;
baseDelay: number;
maxDelay: number;
jitter: boolean;
retryIf?: (error: Error) => boolean;
onRetry?: (error: Error, attempt: number) => void;
}
const defaultOptions: RetryOptions = {
maxAttempts: 3,
baseDelay: 1000,
maxDelay: 30000,
jitter: true,
};
async function retry<T>(
fn: (attempt: number) => Promise<T>,
opts?: Partial<RetryOptions>,
): Promise<T> {
const options = { ...defaultOptions, ...opts };
let lastError: Error;
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
try {
return await fn(attempt);
} catch (err) {
lastError = err instanceof Error ? err : new Error(String(err));
if (attempt === options.maxAttempts) break;
if (options.retryIf && !options.retryIf(lastError)) break;
let delay = Math.min(
options.baseDelay * Math.pow(2, attempt - 1),
options.maxDelay,
);
if (options.jitter) delay *= 0.5 + Math.random();
options.onRetry?.(lastError, attempt);
await new Promise(r => setTimeout(r, delay));
}
}
throw lastError!;
}
// Circuit breaker
class CircuitBreaker {
private failures = 0;
private lastFailure = 0;
private state: 'closed' | 'open' | 'half-open' = 'closed';
constructor(
private threshold: number = 5,
private resetTimeout: number = 60000,
) {}
async execute<T>(fn: () => Promise<T>): Promise<T> {
if (this.state === 'open') {
if (Date.now() - this.lastFailure > this.resetTimeout) {
this.state = 'half-open';
} else {
throw new Error('Circuit breaker is OPEN');
}
}
try {
const result = await fn();
this.failures = 0;
this.state = 'closed';
return result;
} catch (err) {
this.failures++;
this.lastFailure = Date.now();
if (this.failures >= this.threshold) this.state = 'open';
throw err;
}
}
}
// Usage
async function main() {
let callCount = 0;
const result = await retry(
async (attempt) => {
callCount++;
if (callCount < 3) throw new Error(`Fail #${callCount}`);
return 'Success!';
},
{
maxAttempts: 5,
baseDelay: 100,
onRetry: (err, attempt) => console.log(`Retry ${attempt}: ${err.message}`),
},
);
console.log(result);
}
main();Use Cases
- API call resilience
- Database reconnection
- Transient error recovery
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
pythonintermediate
Retry Decorator with Exponential Backoff
Generic retry decorator with configurable attempts, exponential backoff, and exception filtering.
Best for: Network request resilience
#decorator#retry
pythonbeginner
Tenacity Retry with Backoff
Add robust retry logic with exponential backoff, jitter, and conditional retry using the tenacity library.
Best for: Flaky API calls
#retry#tenacity
pythonintermediate
Retry Logic for Data Pipelines
Configurable retry decorator with exponential backoff and jitter for resilient data pipeline tasks.
Best for: Resilient API calls in data pipelines
#retry#resilience
javaintermediate
Retry Mechanism with Exponential Backoff
Implement retries with exponential backoff, jitter, max attempts, and exception-specific handling.
Best for: Resilient API calls with transient failure handling
#java#retry