rust 49 lines · 8 steps

Async retry with exponential backoff in Rust

A generic async helper retries a fallible operation, backing off exponentially with jitter until it succeeds or runs out of attempts.

Explained by highlit
1use std::time::Duration;
2use tokio::time::sleep;
3 
4#[derive(Debug)]
5pub struct RetryConfig {
6 pub max_attempts: u32,
7 pub base_delay: Duration,
8 pub max_delay: Duration,
9}
10 
11impl Default for RetryConfig {
12 fn default() -> Self {
13 Self {
14 max_attempts: 5,
15 base_delay: Duration::from_millis(200),
16 max_delay: Duration::from_secs(30),
17 }
18 }
19}
20 
21pub async fn retry_with_backoff<F, Fut, T, E>(
22 config: &RetryConfig,
23 mut operation: F,
24) -> Result<T, E>
25where
26 F: FnMut() -> Fut,
27 Fut: std::future::Future<Output = Result<T, E>>,
28 E: std::fmt::Display,
29{
30 let mut attempt = 0;
31 
32 loop {
33 attempt += 1;
34 match operation().await {
35 Ok(value) => return Ok(value),
36 Err(err) if attempt >= config.max_attempts => {
37 tracing::error!(attempt, %err, "operation failed, exhausted retries");
38 return Err(err);
39 }
40 Err(err) => {
41 let exp = config.base_delay.saturating_mul(1 << (attempt - 1));
42 let delay = exp.min(config.max_delay);
43 let jitter = Duration::from_millis(fastrand::u64(0..=100));
44 tracing::warn!(attempt, ?delay, %err, "retrying after backoff");
45 sleep(delay + jitter).await;
46 }
47 }
48 }
49}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Exponential backoff with a capped maximum and random jitter spreads out retries and avoids thundering-herd retries.
  2. 2Generic bounds over a future-returning closure let one helper wrap any async fallible operation.
  3. 3Saturating arithmetic and a max clamp keep the delay calculation safe from overflow at high attempt counts.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Async retry with exponential backoff in Rust — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code