Xuanwo/backon

Make retry like a built-in feature provided by Rust.

Rust

1,062

130 commits

updated Jun 19, 2026

See the code

README

BackON   Build Status Latest Version

BackON

Make retry like a built-in feature provided by Rust.

  • Simple API: Native feel: your_fn.retry(ExponentialBuilder::default()).await.
  • Sync & Async: Supports both blocking and async operations seamlessly.
  • Precise Control: Define when to retry and get notified via when and notify.
  • Custom Strategies: Use built-in backoff strategies (exponential, constant) or define custom ones. Also supports dynamic backoff, such as using the HTTP Retry-After header.
  • Cross-Platform: Works everywhere Rust does, including wasm & no-std.

Quick Start

For more examples, check out the examples.

Retry an async function.

use anyhow::Result;
use backon::ExponentialBuilder;
use backon::Retryable;

async fn fetch() -> Result<String> {
    Ok("hello, world!".to_string())
}

#[tokio::main]
async fn main() -> Result<()> {
    let content = fetch
        // Retry with exponential backoff
        .retry(ExponentialBuilder::default())
        // Sleep implementation, required if no feature has been enabled
        .sleep(tokio::time::sleep)
        // When to retry
        .when(|e| e.to_string() == "EOF")
        // Notify when retrying
        .notify(|err: &anyhow::Error, dur: Duration| {
            println!("retrying {:?} after {:?}", err, dur);
        })
        .await?;
    println!("fetch succeeded: {}", content);

    Ok(())
}

Retry a blocking function.

use anyhow::Result;
use backon::BlockingRetryable;
use backon::ExponentialBuilder;

fn fetch() -> Result<String> {
    Ok("hello, world!".to_string())
}

fn main() -> Result<()> {
    let content = fetch
        // Retry with exponential backoff
        .retry(ExponentialBuilder::default())
        // Sleep implementation, required if no feature has been enabled
        .sleep(std::thread::sleep)
        // When to retry
        .when(|e| e.to_string() == "EOF")
        // Notify when retrying
        .notify(|err: &anyhow::Error, dur: Duration| {
            println!("retrying {:?} after {:?}", err, dur);
        })
        .call()?;
    println!("fetch succeeded: {}", content);

    Ok(())
}

Contributing

Check out the CONTRIBUTING.md guide for more details on getting started with contributing to this project.

Getting help

Submit issues for bug report or asking questions in discussion.

License

Licensed under Apache License, Version 2.0.

async
backoff
retry
rust

Xuanwo/backon

Make retry like a built-in feature provided by Rust.

Rust

1,062

130 commits

updated Jun 19, 2026

See the code

README

BackON   Build Status Latest Version

BackON

Make retry like a built-in feature provided by Rust.

  • Simple API: Native feel: your_fn.retry(ExponentialBuilder::default()).await.
  • Sync & Async: Supports both blocking and async operations seamlessly.
  • Precise Control: Define when to retry and get notified via when and notify.
  • Custom Strategies: Use built-in backoff strategies (exponential, constant) or define custom ones. Also supports dynamic backoff, such as using the HTTP Retry-After header.
  • Cross-Platform: Works everywhere Rust does, including wasm & no-std.

Quick Start

For more examples, check out the examples.

Retry an async function.

use anyhow::Result;
use backon::ExponentialBuilder;
use backon::Retryable;

async fn fetch() -> Result<String> {
    Ok("hello, world!".to_string())
}

#[tokio::main]
async fn main() -> Result<()> {
    let content = fetch
        // Retry with exponential backoff
        .retry(ExponentialBuilder::default())
        // Sleep implementation, required if no feature has been enabled
        .sleep(tokio::time::sleep)
        // When to retry
        .when(|e| e.to_string() == "EOF")
        // Notify when retrying
        .notify(|err: &anyhow::Error, dur: Duration| {
            println!("retrying {:?} after {:?}", err, dur);
        })
        .await?;
    println!("fetch succeeded: {}", content);

    Ok(())
}

Retry a blocking function.

use anyhow::Result;
use backon::BlockingRetryable;
use backon::ExponentialBuilder;

fn fetch() -> Result<String> {
    Ok("hello, world!".to_string())
}

fn main() -> Result<()> {
    let content = fetch
        // Retry with exponential backoff
        .retry(ExponentialBuilder::default())
        // Sleep implementation, required if no feature has been enabled
        .sleep(std::thread::sleep)
        // When to retry
        .when(|e| e.to_string() == "EOF")
        // Notify when retrying
        .notify(|err: &anyhow::Error, dur: Duration| {
            println!("retrying {:?} after {:?}", err, dur);
        })
        .call()?;
    println!("fetch succeeded: {}", content);

    Ok(())
}

Contributing

Check out the CONTRIBUTING.md guide for more details on getting started with contributing to this project.

Getting help

Submit issues for bug report or asking questions in discussion.

License

Licensed under Apache License, Version 2.0.

async
backoff
retry
rust

Significant stargazers

(top 24 of 53)

Renée

498 followers · starred Aug 2024

Marco Ieni

426 followers · starred Jun 2023

Koichi Shiraishi

781 followers · starred Aug 2026

dentiny

325 followers · starred Feb 2025