AJAX - AJAX Retry Strategies with Exponential Backoff
AJAX applications communicate with servers over a network, and network communication is not always reliable. Temporary failures such as network interruptions, server overload, slow internet connections, or gateway timeouts can cause AJAX requests to fail. Simply displaying an error message after the first failure may result in a poor user experience, especially when the problem is only temporary. To improve reliability, developers often implement retry mechanisms that automatically resend failed requests. One of the most effective approaches is Exponential Backoff, which gradually increases the waiting time between retry attempts instead of retrying immediately.
What is Exponential Backoff?
Exponential Backoff is a retry strategy where the application waits for an increasing amount of time before making each subsequent retry. Instead of sending repeated requests at fixed intervals, the delay doubles after every failed attempt. This prevents the server from becoming overwhelmed with repeated requests and gives it time to recover from temporary issues.
For example, if the initial delay is one second, the retry sequence might look like this:
-
First retry: 1 second
-
Second retry: 2 seconds
-
Third retry: 4 seconds
-
Fourth retry: 8 seconds
-
Fifth retry: 16 seconds
This strategy is widely used in cloud services, APIs, distributed systems, and modern web applications because it balances reliability and server performance.
Why Immediate Retries Are a Bad Practice
Suppose an AJAX request fails because the server is temporarily overloaded. If thousands of users retry immediately, the server receives another large wave of requests before it has recovered. This can worsen the problem and delay recovery.
Consider an online ticket booking website during a festival sale. If every failed request is retried instantly, the server experiences continuous pressure, increasing the chances of further failures. Exponential Backoff spreads out retry attempts over time, reducing unnecessary traffic and allowing the server to stabilize.
How Exponential Backoff Works
The retry process generally follows these steps:
-
Send the AJAX request.
-
If the request succeeds, process the response normally.
-
If the request fails due to a temporary problem, wait for a specified delay.
-
Retry the request.
-
If the retry fails again, double the waiting time.
-
Continue until either the request succeeds or the maximum retry limit is reached.
This method prevents continuous rapid-fire requests and improves the chances of successful communication.
Formula for Calculating Delay
The delay is commonly calculated using the following formula:
Delay = Base Delay × (2 ^ Retry Attempt)
Where:
-
Base Delay is the initial waiting period.
-
Retry Attempt is the current retry number.
Example:
Base Delay = 1000 milliseconds
| Retry Attempt | Delay |
|---|---|
| 1 | 1000 ms |
| 2 | 2000 ms |
| 3 | 4000 ms |
| 4 | 8000 ms |
| 5 | 16000 ms |
Example Scenario
Imagine a weather application requesting current weather data from an API.
-
The AJAX request is sent.
-
The API server is temporarily unavailable.
-
The application waits one second.
-
It retries.
-
The server is still unavailable.
-
The application waits two seconds.
-
Another retry is attempted.
-
The server becomes available.
-
The weather information is displayed successfully.
The user experiences only a brief delay instead of receiving an immediate failure message.
JavaScript Example Using Fetch API
function fetchWithRetry(url, retries, delay) {
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error("Request Failed");
}
return response.json();
})
.then(data => {
console.log("Success:", data);
})
.catch(error => {
if (retries > 0) {
console.log(`Retrying in ${delay} milliseconds...`);
setTimeout(() => {
fetchWithRetry(url, retries - 1, delay * 2);
}, delay);
} else {
console.log("Maximum retries reached.");
}
});
}
fetchWithRetry("https://api.example.com/data", 5, 1000);
In this example:
-
The application starts with a one-second delay.
-
Every failed retry doubles the waiting period.
-
The retry process stops after five unsuccessful attempts.
-
If any retry succeeds, no further retries are performed.
Adding Random Jitter
When many users access the same application simultaneously, they might all retry at exactly the same intervals. This creates bursts of traffic that can overwhelm the server.
To solve this, developers often introduce jitter, which adds a small random delay to each retry.
Example:
Instead of retrying exactly after four seconds, the application may retry after:
-
3.8 seconds
-
4.3 seconds
-
4.6 seconds
-
3.9 seconds
This spreads requests more evenly across time and reduces the likelihood of synchronized traffic spikes.
Example code:
const jitter = Math.random() * 500;
const nextDelay = delay * 2 + jitter;
Which Errors Should Be Retried?
Not every AJAX failure should trigger a retry.
Retries are generally appropriate for:
-
Network connection failures
-
Server timeout errors
-
HTTP 500 Internal Server Error
-
HTTP 502 Bad Gateway
-
HTTP 503 Service Unavailable
-
HTTP 504 Gateway Timeout
Retries are generally not appropriate for:
-
HTTP 400 Bad Request
-
HTTP 401 Unauthorized
-
HTTP 403 Forbidden
-
HTTP 404 Not Found
-
Invalid request parameters
-
Authentication failures
These errors usually require changes to the request or user action rather than another attempt.
Setting a Maximum Retry Limit
An application should never retry indefinitely. A maximum retry limit ensures that the application eventually stops attempting and reports the failure if the issue persists.
For example:
-
Maximum retries: 5
-
Initial delay: 1 second
-
Total wait time: 1 + 2 + 4 + 8 + 16 = 31 seconds
If the request still fails after these attempts, the application should notify the user and offer options such as trying again manually.
Benefits of Exponential Backoff
Exponential Backoff offers several advantages:
-
Reduces unnecessary network traffic.
-
Prevents overwhelming servers during temporary outages.
-
Improves the reliability of AJAX-based applications.
-
Enhances user experience by automatically recovering from transient failures.
-
Conserves bandwidth and system resources.
-
Aligns with best practices used by cloud providers and API platforms.
Limitations
Although effective, Exponential Backoff has some limitations:
-
Users may experience longer waits if repeated retries are required.
-
It cannot resolve permanent errors such as invalid credentials or incorrect URLs.
-
Choosing an unsuitable base delay or retry count may lead to either excessive waiting or insufficient recovery time.
-
Additional logic is needed to distinguish between retryable and non-retryable errors.
Best Practices
When implementing Exponential Backoff in AJAX applications:
-
Retry only temporary or transient failures.
-
Set a reasonable maximum retry count.
-
Begin with a short initial delay, such as one second.
-
Double the delay after each unsuccessful attempt.
-
Add random jitter to prevent synchronized retries.
-
Log retry attempts for monitoring and debugging.
-
Inform users when all retry attempts have failed.
-
Avoid retrying client-side errors such as malformed requests or authorization failures.
Conclusion
Exponential Backoff is a robust retry strategy that significantly improves the resilience of AJAX applications. By progressively increasing the delay between retry attempts, it minimizes unnecessary server load, reduces network congestion, and increases the likelihood of successful communication after temporary failures. Combined with appropriate retry limits, error classification, and jitter, Exponential Backoff helps developers build reliable, efficient, and user-friendly web applications that can gracefully handle intermittent network and server issues.