Retries with exponential backoff and jitter

Distributed systems Mid-level Python 3.13+ PostgreSQL 17+ Reviewed By Best Latest Apps

Predict the output

What ceilings does this full-jitter backoff use for six attempts?

Python 3.13
import random


def backoff_delays(
    attempts: int, base: float, cap: float, rng: random.Random
) -> list[float]:
    """Full jitter: a random wait between 0 and the ceiling."""
    delays = []
    for attempt in range(attempts):
        ceiling = min(cap, base * 2**attempt)
        delays.append(rng.uniform(0, ceiling))
    return delays


ceilings = [min(10.0, 0.5 * 2**a) for a in range(6)]
print("ceilings:", ceilings)
d = backoff_delays(6, 0.5, 10.0, random.Random(7))
print(
    "all within ceiling:", all(0 <= x <= c for x, c in zip(d, ceilings))
)

Options
Hint 1 of 1

What does min(cap, ...) do on the sixth attempt?

Choose an answer, then open Show answer below to check it.

Five clients fail at t = 0 and retry three times. With a fixed 1 s wait all five hit the server in the same second each time; exponential backoff spaces the waves but each wave still arrives together; full jitter spreads the attempts out, so the retries no longer land on the same instant and the later waves blur together.

Illustrative; not a load test

Text version
Retries reaching the server per second
Strategy0 to <1 s1 to <2 s2 to <3 s3 to <4 s4 to <5 s5 to <6 s6 to <7 s7 to <8 s
Fixed 1 s wait05550000
Exponential05050005
Exponential + full jitter54402000

Fixed 1 s wait: C1 at 0, 1, 2, 3 s; C2 at 0, 1, 2, 3 s; C3 at 0, 1, 2, 3 s; C4 at 0, 1, 2, 3 s; C5 at 0, 1, 2, 3 s.

Exponential: C1 at 0, 1, 3, 7 s; C2 at 0, 1, 3, 7 s; C3 at 0, 1, 3, 7 s; C4 at 0, 1, 3, 7 s; C5 at 0, 1, 3, 7 s.

Exponential + full jitter: C1 at 0, 0.2, 1.3, 2.8 s; C2 at 0, 0.6, 1.9, 2.2 s; C3 at 0, 0, 1.7, 2.7 s; C4 at 0, 0.2, 2.2, 4.1 s; C5 at 0, 0.8, 1.8, 4.4 s.

Show answer

Answer: A ceilings: [0.5, 1.0, 2.0, 4.0, 8.0, 10.0] then all within ceiling: True

Correct. Doubles from 0.5 s and stops at the 10 s cap; every random delay stays under its ceiling.

Each ceiling is base × 2^attempt, cut off at the cap: 0.5, 1, 2, 4, 8, then 16 capped to 10. Full jitter draws the real wait uniformly between 0 and that ceiling, so it never goes over.

Why not the others?
  • B ceilings: [0.5, 1.0, 2.0, 4.0, 8.0, 16.0] then all within ceiling: True. The cap limits the last one to 10 s.
  • C ceilings: [0.5, 1.0, 1.5, 2.0, 2.5, 3.0] then all within ceiling: True. That's linear backoff.
  • D ceilings: [0.5, 1.0, 2.0, 4.0, 8.0, 10.0] then all within ceiling: False. uniform(0, c) never exceeds c.

30-second answer

Retry only failures that might succeed later (timeouts, 503, 429, connection resets) and only for idempotent operations or ones protected by an idempotency key. Wait longer after each attempt (exponential backoff) with a cap, and randomize each wait (jitter) so clients that failed together don't all retry together. Limit attempts, respect Retry-After, and keep a retry budget so retries can't multiply the load.

Practise saying it · 40 s. No recording, just a timer

How should clients retry?

Say your answer out loud, then check which of these points you covered:

  • Only retryable errors
  • Idempotent or keyed
  • Exponential backoff with a cap
  • Jitter
  • Limits and budgets

Deep dive

Full jitter: sleep a random time between 0 and min(cap, base × 2^attempt).

Retrying at every layer multiplies: 3 retries at each of 3 layers can turn 1 request into 64 attempts.

A retry budget (for example, retries at most 10% of requests) keeps an outage from doubling traffic.

Don't retry 400, 401, 403, 404 or 422: the same request will fail the same way.

Common mistakes

  • Retrying immediately in a tight loop.
  • Retrying non-idempotent POSTs without an idempotency key.
  • Retrying at the client, the gateway and the service all at once.

Senior take & follow-ups

Cover what to retry, backoff with a cap, jitter, attempt limits and retry budgets.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why does jitter matter if backoff already spreads retries?

    Show hint

    Without it, clients that failed at the same moment retry at the same moments.

  2. What does Retry-After tell you?

    Show hint

    How long the server wants you to wait (seconds or a date).

Similar on Android: Chaining work and constraints WorkManager applies exponential backoff for you on the device; on the server you choose the cap, jitter and budget.

Suggest a fix if something here is wrong or out of date.