JAVASCRIPT
Robust API Request Retries with Exponential Backoff
Enhance API integration reliability by implementing an exponential backoff retry mechanism for failed requests, preventing rate limit issues and transient errors.
const axios = require('axios');
async function callApiWithRetries(apiCallFn, maxRetries = 5, initialDelay = 1000) {
let retries = 0;
while (retries < maxRetries) {
try {
return await apiCallFn();
} catch (error) {
// Check for common retryable errors: 429 Too Many Requests, 5xx server errors
const statusCode = error.response ? error.response.status : null;
if ([429, 500, 502, 503, 504].includes(statusCode) && retries < maxRetries - 1) {
const delay = initialDelay * Math.pow(2, retries) + Math.random() * 500; // Exponential backoff with jitter
console.warn(`API call failed (status: ${statusCode}). Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
retries++;
} else {
// Not a retryable error or max retries reached
console.error('API call failed permanently:', error.response ? error.response.data : error.message);
throw error;
}
}
}
throw new Error('Max retries reached, API call failed.');
}
// Example API function to wrap
const fetchUserData = async (userId) => {
console.log(`Attempting to fetch data for user ${userId}`);
// Simulate an API call that might fail
const randomFailure = Math.random();
if (randomFailure < 0.3) { // 30% chance of a 429 error
const error = new Error('Simulated 429 Too Many Requests');
error.response = { status: 429, data: { message: 'Rate limit exceeded' } };
throw error;
}
if (randomFailure > 0.8) { // 20% chance of a 500 error
const error = new Error('Simulated 500 Internal Server Error');
error.response = { status: 500, data: { message: 'Server error' } };
throw error;
}
return { userId, name: `User ${userId}`, data: 'Some data from API' };
};
// Usage:
// (async () => {
// try {
// const data = await callApiWithRetries(() => fetchUserData(123));
// console.log('Successfully fetched data:', data);
// } catch (err) {
// console.error('Failed after retries:', err.message);
// }
// })();
How it works: This snippet provides a robust strategy for handling transient API errors and rate limits using exponential backoff with jitter. It wraps an asynchronous API call function, automatically retrying the request with increasing delays if specific HTTP status codes (like 429 for rate limits or 5xx server errors) are encountered. Jitter (random additional delay) is added to prevent all clients from retrying simultaneously, reducing the chance of overwhelming the API again.