PIXELBANKv9.1.0
Menu

Exponential Backoff Schedule with Jitter Bounds

Problem Statement

A tool returns 429. The agent retries immediately, gets another 429, retries again - and a transient blip becomes a self-inflicted outage, with every concurrent agent hammering in lockstep. Exponential backoff spaces the retries out; jitter breaks the lockstep. Before shipping either, you want to know the actual numbers: how long the worst case takes, and when the growth flattens against the cap.

Background

For a 0-based attempt index ii, the nominal delay is

di=min⁡(cap, base⋅factor i)d_i = \min(\text{cap},\ \text{base} \cdot \text{factor}^{\,i})

Jitter turns each fixed delay into a range. With a jitter fraction j∈[0,1]j \in [0, 1] the actual sleep is drawn uniformly from

[ di(1−j), di ][\,d_i (1 - j),\ d_i\,]

so j=0j = 0 is no jitter, j=0.5j = 0.5 is "equal jitter" and j=1j = 1 is "full jitter" (the range starts at zero). You are computing the deterministic bounds, not sampling - the schedule must be reproducible.

Your Task

Implement:

def backoff_schedule(base, factor, cap, attempts, jitter):

Return a dict:

  • delays: list of [lo, hi] pairs, one per attempt, each rounded to 4 decimal places.
  • best_case_total: sum of the (already rounded) lo values, rounded to 4 dp.
  • worst_case_total: sum of the (already rounded) hi values, rounded to 4 dp.
  • capped_at: the smallest 0-based attempt index whose uncapped delay base * factori** is >= cap, or -1 if the cap is never reached within attempts.

Input/Output Format

All floats are rounded to 4 decimal places. capped_at is an int. With attempts = 0, delays is empty and both totals are 0.0.

Sample

print(backoff_schedule(1.0, 2.0, 8.0, 5, 0.5)["delays"])
# [[0.5, 1.0], [1.0, 2.0], [2.0, 4.0], [4.0, 8.0], [4.0, 8.0]]

Delays double until they hit the 8.0 cap at attempt 3, and equal jitter puts the lower bound at half of each.

Example:

Input:
print(backoff_schedule(1.0, 2.0, 8.0, 5, 0.5)['delays'])
Output:
[[0.5, 1.0], [1.0, 2.0], [2.0, 4.0], [4.0, 8.0], [4.0, 8.0]]
Reasoning:

Uncapped delays are 1, 2, 4, 8, 16; the cap of 8.0 clamps attempts 3 and 4 to 8.0. Equal jitter (j = 0.5) sets each lower bound to d * (1 - 0.5) = d / 2.

Constraints:

  • base > 0, factor >= 1.0, cap > 0, 0 <= attempts <= 64, 0 <= jitter <= 1
  • Attempt indices are 0-based: the first delay is base * factor**0 = base
  • Every delay bound is rounded to 4 decimal places
  • Totals are the sums of the already-rounded bounds, rounded again to 4 dp
  • capped_at compares the uncapped delay against cap using >=
  • Never emit a raw unrounded float
solution.py

Test Results

0/0
Run code to see test results.
Exponential Backoff Schedule with Jitter Bounds - Easy | PixelBank