DEV Community

Leandro Lucas
Leandro Lucas

Posted on

backon — The Modern Python Retry Library You've Been Waiting For

backon — The Modern Python Retry Library You've Been Waiting For

If you've written Python code that talks to external APIs, databases, or network services, you've needed retry logic. The Python ecosystem has several options:

  • backoff (2.7k ★) — The most popular, but now archived and no longer maintained
  • tenacity — In maintenance mode, limited features
  • retrying — Unmaintained since 2021

Enter backon, the modern evolution of backoff.

pip install backon

Why backon?

backon is a zero-dependency Python library that provides four APIs for retry: decorator, functional, context manager, and callable. It works with both sync and async code out of the box.

1. Retry on Exception (Decorator)

import backon

@backon.on_exception(backon.expo, ValueError, max_tries=3)
def fetch_data():
    return api.call()
Enter fullscreen mode Exit fullscreen mode

2. Retry on Predicate

@backon.on_predicate(backon.constant, max_tries=5, interval=0.5)
def poll_status():
    return check_ready()
Enter fullscreen mode Exit fullscreen mode

3. Functional API

result = backon.retry(
    fetch_data,
    backon.expo,
    exception=ValueError,
    max_tries=3,
)
Enter fullscreen mode Exit fullscreen mode

4. Context Manager

with backon.Retrying(backon.expo, exception=ValueError, max_tries=3) as r:
    result = r.call(fetch_data)
Enter fullscreen mode Exit fullscreen mode

Async variant:

async with backon.Retrying(backon.constant, exception=ValueError, max_tries=3, interval=0.5) as r:
    result = await r.async_call(fetch_data)
Enter fullscreen mode Exit fullscreen mode

Beyond Basic Retry

backon includes features you won't find in other Python retry libraries:

Circuit Breaker

Three-state circuit breaker (CLOSED/OPEN/HALF_OPEN) with automatic recovery:

from backon._circuit_breaker import BreakerRetrying, CircuitBreaker

breaker = BreakerRetrying(
    backon.expo, max_tries=3,
    breaker=CircuitBreaker(failure_threshold=5, recovery_timeout=60.0),
)
result = breaker.call(fetch)
Enter fullscreen mode Exit fullscreen mode

Hedging

Run multiple retry attempts concurrently, return the first success:

from backon._hedging import hedge

result = hedge(fetch, backon.expo, max_hedge=3)
Enter fullscreen mode Exit fullscreen mode

Prometheus / OpenTelemetry Metrics

Optional metrics with zero hard dependencies:

from backon._instrumentation import PrometheusMetrics, set_metrics_collector
set_metrics_collector(PrometheusMetrics())
Enter fullscreen mode Exit fullscreen mode

Testing Utilities

Skip retry in tests, limit retries, or assert retry behavior:

from backon._testing import disable_retries, assert_retried

with disable_retries():
    result = fetch()  # no retry

assert_retried(fetch, expected_tries=3)
Enter fullscreen mode Exit fullscreen mode

Full Feature List

  • Zero dependencies — pure Python, stdlib only
  • Four APIs — decorator, functional, context manager, callable
  • Async native — same API works for async def
  • Full type hints — validated with mypy, strict mode compatible
  • Global toggle — backon.disable() / backon.enable() for testing
  • Multiple wait strategies — exponential, constant, Fibonacci, decay, runtime
  • Jitter — full jitter, random jitter, or none
  • Rich callbacks — on_attempt, on_backoff, on_success, on_giveup
  • Circuit breaker — CLOSED/OPEN/HALF_OPEN with automatic recovery
  • Hedging — concurrent retry, first-success-wins
  • Prometheus / OpenTelemetry metrics
  • Testing module — disable_retries(), limit_retries(), remove_backoff()
  • Trio support
  • Operator overloading — compose stops with | / &, waits with +
  • Iterator API — for attempt in Retrying(...):

Migrating from backoff

It's a near-drop-in replacement:

- import backoff
+ import backon

- @backoff.on_exception(backoff.expo, ValueError, max_tries=3)
+ @backon.on_exception(backon.expo, ValueError, max_tries=3)
Enter fullscreen mode Exit fullscreen mode

Quick Install

pip install backon
Enter fullscreen mode Exit fullscreen mode

Requires Python 3.10+.


Links:

Top comments (0)