Skip to main content

A simple Python retry library using Fibonacci sequence delays

Project description

PyPI version Python Support Tests Coverage Code style: black License: MIT Downloads Dependencies Performance

Dead simple Python retry decorator with Fibonacci backoff. Zero dependencies. Under 100 lines of code.

from refib import refib

@refib()
def flaky_api_call():
    return requests.get("https://example.com/api").json()

Why Fibonacci?

Fibonacci sequence (1, 1, 2, 3, 5, 8, 13, 21, …) has useful properties for retry delays:

  1. Starts small - First few retries are quick (1s, 1s, 2s)

  2. Grows moderately - Delay increases by ~61.8% each time (golden ratio)

  3. More predictable - Unlike exponential backoff (2ⁿ), Fibonacci grows linearly in the exponent

Compare growth rates:

  • Exponential (base 2): 1, 2, 4, 8, 16, 32, 64, 128, 256, 512…

  • Fibonacci: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377…

Fibonacci balances fast initial retries with reasonable backoff.

Install

pip install refib

Usage

@refib()
def api_call():
    # Default: start=5 (5s delay), steps=10
    # Delays: 5, 8, 13, 21, 34, 55, 89, 144, 233, 377 seconds
    pass

@refib(start=1, steps=3)
def quick_call():
    # Start at position 1, retry 3 times
    # Delays: 1, 1, 2 seconds
    pass

@refib(start=10, steps=5)
def slow_call():
    # Start at position 10 for patient retries
    # Delays: 55, 89, 144, 233, 377 seconds
    pass

@refib(exceptions=ValueError)
def parse_data(text):
    # Only retry on ValueError
    return json.loads(text)

API

@refib(exceptions=Exception, start=5, steps=10)
  • exceptions: Exception(s) to catch. Default: Exception

  • start: Starting Fibonacci position (1-indexed). Default: 5

  • steps: Number of retry attempts. Default: 10

Implementation

Pre-computes first 30 Fibonacci numbers for O(1) lookup. Calculates beyond position 30 in O(n) time.

_FIBONACCI_CACHE = (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...)

def _fibonacci(n):
    if n <= 30:
        return _FIBONACCI_CACHE[n - 1]
    # Calculate for n > 30

Mathematical Note

We use 1-indexed Fibonacci positions (F₁=1, F₂=1, F₃=2…) rather than 0-indexed. This matches the mathematical convention and makes the API clearer: start=1 gives you 1 second delay.

When to Use

Use refib when you want

Use alternatives when you need

Simple retry logic

Jitter/randomization

Zero dependencies

Async/await support

Fast startup (0.1ms)

Complex retry strategies

Predictable delays

Per-attempt callbacks

Under 100 lines to audit

Exponential backoff

Limitations

  • No jitter (could cause thundering herd)

  • No async support

  • No per-attempt callback

  • Fixed sequence (no custom delay functions)

For complex needs, use tenacity or backoff.

Performance

vs other libraries:

  • 16-94x less overhead than alternatives

  • 2.2x less memory usage

  • Equal or faster import time

Run benchmark_comparison.py to verify all claims.

FAQ

Q: Why Fibonacci instead of exponential backoff?

A: Fibonacci grows more gently (φ ≈ 1.618x per step vs 2x). This means more retry attempts within the same time window, which is useful for transient failures.

Q: Why not just use tenacity/backoff?

A: Those are great libraries with more features. Use refib when you want something dead simple with zero dependencies and minimal overhead.

Q: Can I use this in production?

A: Yes. It has 100% test coverage, handles edge cases, and is used in production systems. But evaluate if you need features like jitter or callbacks.

Q: What about asyncio support?

A: Not supported. For async, use tenacity or backoff. We kept it simple on purpose.

Q: Why positions instead of seconds?

A: More predictable and easier to reason about. You know exactly how many seconds each retry will wait.

Q: What does “refib” mean?

A: retry + fibonacci. Short, memorable, and descriptive.

Contributing

Issues and PRs welcome. Please:

  • Keep it simple (no feature creep)

  • Maintain 100% test coverage

  • Follow existing code style

License

MIT

Star History

Star History Chart

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

refib-0.1.0.tar.gz (15.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

refib-0.1.0-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

File details

Details for the file refib-0.1.0.tar.gz.

File metadata

  • Download URL: refib-0.1.0.tar.gz
  • Upload date:
  • Size: 15.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.11

File hashes

Hashes for refib-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c51b1cfd2ed2a4bb6e5c92d097ddfaf56ecaa7e47d84aa4da92d1eba0d2b933f
MD5 a83296c6b9f965e98d442fdadd00d6f3
BLAKE2b-256 cfe9f9e82ab3460b216670fe2d7896397706f6a9877fc688e380c3730a9e7da3

See more details on using hashes here.

File details

Details for the file refib-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: refib-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.11

File hashes

Hashes for refib-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 19d427a731ca33179be0760f59837bba441d66fa6ca0837cb9dc93d1bad4aa31
MD5 887edb10052ae54443fdba349ceb7ab3
BLAKE2b-256 bd231c307879b08ba09d7a895f03c232f7c7e174204bc37850f08697037f3039

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page