A simple Python retry library using Fibonacci sequence delays
Project description
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:
Starts small - First few retries are quick (1s, 1s, 2s)
Grows moderately - Delay increases by ~61.8% each time (golden ratio)
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)
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c51b1cfd2ed2a4bb6e5c92d097ddfaf56ecaa7e47d84aa4da92d1eba0d2b933f
|
|
| MD5 |
a83296c6b9f965e98d442fdadd00d6f3
|
|
| BLAKE2b-256 |
cfe9f9e82ab3460b216670fe2d7896397706f6a9877fc688e380c3730a9e7da3
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19d427a731ca33179be0760f59837bba441d66fa6ca0837cb9dc93d1bad4aa31
|
|
| MD5 |
887edb10052ae54443fdba349ceb7ab3
|
|
| BLAKE2b-256 |
bd231c307879b08ba09d7a895f03c232f7c7e174204bc37850f08697037f3039
|