Skip to content

Backoff & jitter

The problem

Retrying immediately hammers a service that's already struggling, and a fleet of clients retrying on the same schedule arrives in synchronised waves — a thundering herd.

The solution

Wait longer after each failure (exponential backoff), put a ceiling on the wait (a cap), and scatter each delay randomly (jitter) so clients spread out.

ts
await retry(callApi, {
  times: 6,
  initialDelayTime: 200, // first retry waits 200ms
  backoffFactor: 2, // then 400, 800, 1600…
  maxDelayTime: 5_000, // never wait longer than 5s
  jitter: 'full', // randomise within [0, delay]
});
  • backoffFactor1 keeps the delay constant, 2 doubles it, 3 is steeper.
  • maxDelayTime — clamps the growth, e.g. 100 → 200 → 400 → 500 → 500….
  • jitter'equal' (or true) randomises within [delay / 2, delay]; 'full' within [0, delay]. false keeps the exact delay.

Try it

Switch jitter between off, equal and full, and watch the spacing change.

attempt timelineidle
  • failed
  • timed out
  • bailed
  • pending
  • succeeded

Each marker sits at its real elapsed time — backoff pushes them apart, the cap reins them in, jitter scatters them.

  1. Press Run to start.