Backoff Strategy Comparison
Backoff Strategy Comparison¶
This comparison assumes initial_delay = 1s for all strategies. Actual delays depend on your retry configuration. All strategies are capped by max_delay (default 30s) as enforced in src/cook/retry_v2.rs:304.
Source: Delay calculations from src/cook/retry_v2.rs:284-305 (calculate_delay method)
Strategy Comparison Table¶
| Strategy | Attempt 1 | Attempt 2 | Attempt 3 | Attempt 4 | Attempt 5 | Best For |
|---|---|---|---|---|---|---|
| Fixed (2s) | 2s | 2s | 2s | 2s | 2s | Predictable timing, simple errors without exponential backpressure |
| Linear (+2s) | 1s | 3s | 5s | 7s | 9s | Moderate load reduction, gradual backoff without aggressive delays |
| Exponential (base 2.0) | 1s | 2s | 4s | 8s | 16s | Recommended default - Aggressive backoff for most failures, best for temporary outages |
| Fibonacci | 1s | 1s | 2s | 3s | 5s | Gentler than exponential, good for rate limits or distributed systems |
| Custom | user-defined | user-defined | user-defined | user-defined | user-defined | Specific delay patterns, custom business logic |
Note: Exponential is the default backoff strategy (see src/cook/retry_v2.rs:92-97)
Strategy Formulas¶
Each strategy calculates delay using a different formula:
Fixed (src/cook/retry_v2.rs:286):
Always returns the same delay, regardless of attempt number.Linear (src/cook/retry_v2.rs:287-289):
Example: Withinitial_delay = 1s and increment = 2s:
- Attempt 1: 1s + 2s × (1-1) = 1s
- Attempt 2: 1s + 2s × (2-1) = 3s
- Attempt 3: 1s + 2s × (3-1) = 5s
Exponential (src/cook/retry_v2.rs:290-292):
Example: Withinitial_delay = 1s and base = 2.0:
- Attempt 1: 1s × 2^(1-1) = 1s × 1 = 1s
- Attempt 2: 1s × 2^(2-1) = 1s × 2 = 2s
- Attempt 3: 1s × 2^(3-1) = 1s × 4 = 4s
The base parameter is configurable (default: 2.0). Common values:
- base = 2.0: Aggressive backoff (doubles each retry)
- base = 1.5: Gentler exponential growth
- base = 3.0: Very aggressive backoff
Fibonacci (src/cook/retry_v2.rs:294-297):
Example: Withinitial_delay = 1s:
- Attempt 1: 1s × fibonacci(1) = 1s × 1 = 1s
- Attempt 2: 1s × fibonacci(2) = 1s × 1 = 1s
- Attempt 3: 1s × fibonacci(3) = 1s × 2 = 2s
- Attempt 4: 1s × fibonacci(4) = 1s × 3 = 3s
- Attempt 5: 1s × fibonacci(5) = 1s × 5 = 5s
Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34...
Custom (src/cook/retry_v2.rs:298-301):
Allows you to specify exact delays for each attempt. If retry exceeds the array length,max_delay is used.
Max Delay Cap¶
All strategies are capped by max_delay (src/cook/retry_v2.rs:304):
This prevents unbounded delays in exponential/fibonacci strategies. Default max_delay = 30s (src/cook/retry_v2.rs:30).
Example with max_delay = 30s and Exponential (base 2.0):
- Attempt 6: Would be 32s → capped to 30s
- Attempt 7+: All capped to 30s
Jitter Support¶
All strategies support optional jitter to prevent thundering herd problems (src/cook/retry_v2.rs:308-317).
When jitter = true (default jitter_factor = 0.3), delays are randomized:
jitter_range = delay * jitter_factor
actual_delay = delay + random(-jitter_range/2, +jitter_range/2)
Example with 1s delay and 30% jitter (factor 0.3): - jitter_range = 1s × 0.3 = 0.3s - actual_delay = random(0.85s, 1.15s)
See Jitter for Distributed Systems for when to use jitter.
YAML Configuration Examples¶
Fixed Delay:
Linear Backoff:
Exponential Backoff (default):
retry_config:
backoff:
type: exponential
base: 2.0 # Optional: default is 2.0
initial_delay: "1s" # 1s, 2s, 4s, 8s, 16s...
max_delay: "30s" # Cap at 30s
Fibonacci Backoff:
Custom Delays:
retry_config:
backoff:
type: custom
delays: ["1s", "2s", "5s", "10s", "30s"]
max_delay: "60s" # Fallback if attempts exceed array length
With Jitter (any strategy):
retry_config:
backoff: exponential
initial_delay: "1s"
jitter: true # Enable randomization
jitter_factor: 0.3 # 30% jitter (±15%)
Choosing the Right Strategy¶
| Use Case | Recommended Strategy | Reasoning |
|---|---|---|
| Temporary service outage | Exponential (base 2.0) | Quickly backs off to avoid overwhelming recovering service |
| Rate limiting (429 errors) | Fibonacci or Linear | Gentler backoff respects rate limits without excessive delays |
| Network flakiness | Exponential + Jitter | Aggressive backoff with jitter prevents thundering herd |
| Predictable timing needs | Fixed | Consistent delay for deterministic behavior |
| Gradual load shedding | Linear | Steady increase allows system to recover gradually |
| Custom business logic | Custom | Full control over delay pattern (e.g., comply with API retry-after headers) |
| Distributed systems | Fibonacci + Jitter | Balances quick retries with avoiding cascade failures |
Default recommendation: Exponential with base = 2.0 is the default for good reason - it works well for most transient failures while avoiding excessive load on failing systems.
Performance Comparison¶
Time to reach max_delay = 30s with initial_delay = 1s:
| Strategy | Attempts to Max | Total Time (5 attempts) |
|---|---|---|
| Fixed (2s) | Never (always 2s) | 10s |
| Linear (+2s) | 15 attempts | 25s (1+3+5+7+9) |
| Exponential (base 2.0) | 5 attempts | 31s (1+2+4+8+16) |
| Fibonacci | 9 attempts | 12s (1+1+2+3+5) |
Key insight: Exponential reaches max delay fastest, making it most aggressive. Fibonacci is gentler, making it better for gradual recovery scenarios.