How to Implement Retry with Exponential Backoff in Node.js
- Published on
- Authors
- Name
- Binh Bui
- @bvbinh
Retry with exponential backoff is a technique used to handle network errors by retrying a failed request after waiting for an increasing amount of time between each retry attempt. This technique is especially useful when dealing with unreliable networks or services that occasionally fail. In this blog post, we will look at how to implement retry with exponential backoff in Node.js.
Using the retry module
The easiest way to implement retry
with exponential backoff in Node.js is to use the retry module. This module provides a convenient API for retrying an operation with configurable retry settings. Here's an example of how to use the retry
module to implement retry with exponential backoff:
const retry = require('retry')
function retryWithExponentialBackoff(operation, options) {
return new Promise((resolve, reject) => {
const operationRetry = retry.operation(options)
operationRetry.attempt(() => {
operation()
.then((result) => {
resolve(result)
})
.catch((err) => {
if (operationRetry.retry(err)) {
return
}
reject(operationRetry.mainError())
})
})
})
}
In this implementation, operation
is a function that performs the network operation that may fail, and options
is an object that specifies the retry configuration. The retry.operation()
method creates a new retry object with the given configuration, and retry.attempt()
method executes the operation and handles retries if it fails.
Implementing retry with exponential backoff from scratch
If you prefer not to use third-party libraries, you can implement retry with exponential backoff in Node.js without much hassle. Here's an example implementation:
function retryWithExponentialBackoff(fn, maxAttempts = 5, baseDelayMs = 1000) {
let attempt = 1
const execute = async () => {
try {
return await fn()
} catch (error) {
if (attempt >= maxAttempts) {
throw error
}
const delayMs = baseDelayMs * 2 ** attempt
console.log(`Retry attempt ${attempt} after ${delayMs}ms`)
await new Promise((resolve) => setTimeout(resolve, delayMs))
attempt++
return execute()
}
}
return execute()
}
In this implementation, fn
is a function that performs the operation that may fail, maxAttempts
is the maximum number of attempts before giving up, and baseDelayMs
is the initial delay before the first retry. The execute
function wraps the operation and handles retries.
When an error occurs during the operation, the execute
function checks whether it should retry the operation. If it should retry, it waits for an increasing amount of time using exponential backoff and then retries the operation. If it shouldn't retry, it throws the error.
Example usage
Here's an example of how to use the retryWithExponentialBackoff function to retry an HTTP request with exponential backoff:
const axios = require('axios')
async function makeRequest() {
const url = 'https://example.com/api/data'
try {
const response = await axios.get(url)
return response.data
} catch (error) {
console.log(`Error: ${error.message}`)
throw error
}
}
async function getDataWithRetries() {
try {
const data = await retryWithExponentialBackoff(makeRequest)
console.log(`Data: ${data}`)
} catch (error) {
console.log(`Failed to get data: ${error.message}`)
}
}
In this example, the getDataWithRetries
function calls the makeRequest
function to make an HTTP request. If the request fails, the getDataWithRetries
function retries the request with exponential backoff. If the request succeeds, the getDataWithRetries
function logs the response data.
Conclusion
In conclusion, retry with exponential backoff is a valuable technique for handling network errors in Node.js. It allows you to retry a failed request after waiting for an increasing amount of time between each retry attempt. Whether you choose to use the retry module or build your own implementation, retry with exponential backoff can help make your Node.js applications more resilient to network errors and ensure that your requests are eventually successful. By using this technique, you can provide a better user experience and reduce the risk of downtime or service disruption.
Further reading
- Node.js retry module documentation: https://www.npmjs.com/package/retry
- Exponential Backoff and Jitter: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
- Retry Patterns for Cloud Applications: https://docs.microsoft.com/en-us/azure/architecture/patterns/retry
- Exponential Backoff: https://en.wikipedia.org/wiki/Exponential_backoff
These resources provide more in-depth information on retry with exponential backoff, as well as additional tips and best practices for handling network errors in Node.js.
Thanks for reading! If you enjoyed this post, please share it with your friends and colleagues. You can also follow me on Twitter for more Node.js tips and tricks.