← Back to all snippets
JAVASCRIPT

Implement API Request Retry with Exponential Backoff

Build a robust client-side API integration by implementing an exponential backoff retry mechanism for failed `fetch` requests, improving reliability.

async function fetchWithRetry(url, options = {}, retries = 3, delay = 1000) {
    let lastError;
    for (let i = 0; i < retries; i++) {
        try {
            const response = await fetch(url, options);
            if (!response.ok && response.status !== 429) { // Exclude 429 for simple retry, handle explicitly if needed
                throw new Error(`HTTP error! Status: ${response.status}`);
            }
            return response; // Success!
        } catch (error) {
            lastError = error;
            console.warn(`Attempt ${i + 1} failed: ${error.message}. Retrying in ${delay}ms...`);
            await new Promise(resolve => setTimeout(resolve, delay));
            delay *= 2; // Exponential backoff
        }
    }
    throw new Error(`Max retries (${retries}) exceeded. Last error: ${lastError ? lastError.message : 'Unknown error'}`);
}

// Example usage:
// fetchWithRetry('https://api.example.com/unreliable-endpoint', { method: 'GET' }, 5, 500)
//     .then(response => response.json())
//     .then(data => console.log('Successfully fetched data after retries:', data))
//     .catch(error => console.error('Failed after all retries:', error.message));

// // Simulate a failing endpoint that eventually succeeds
// let callCount = 0;
// const mockFetch = async (url, options) => {
//     callCount++;
//     if (callCount < 3) { // Fail first 2 attempts
//         console.log(`Mock fetch attempt ${callCount}: Failing`);
//         throw new Error('Simulated network error');
//     }
//     console.log(`Mock fetch attempt ${callCount}: Succeeding`);
//     return new Response(JSON.stringify({ message: 'Success!' }), { status: 200, headers: { 'Content-Type': 'application/json' } });
// };
// global.fetch = mockFetch; // Temporarily override global fetch for demonstration
// fetchWithRetry('https://api.example.com/unreliable-endpoint', {}, 5, 200)
//     .then(response => response.json())
//     .then(data => console.log('Mock Data:', data))
//     .catch(error => console.error('Mock Failed:', error.message));
// delete global.fetch; // Clean up
How it works: This function `fetchWithRetry` enhances standard `fetch` calls by adding a retry mechanism with exponential backoff. If an API request fails due to network issues or non-`2xx` HTTP status codes (excluding `429` for simplicity), it waits for an increasing amount of time before retrying the request. This pattern significantly improves the robustness of integrations with potentially unreliable external APIs, preventing transient failures from crashing an application.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs