How to calculate exponential backoff with jitter

By

Set a base delay, a multiplier, and a cap, then read the wait before each retry. Compare no jitter with full, equal, and decorrelated jitter.

Free toolThis tutorial uses the Exponential Backoff Calculator. It runs in your browser, so open it in another tab and follow along.

Exponential backoff is the wait before each retry. The wait grows by a multiplier, and a cap stops it growing forever. Jitter picks a value inside that wait so a crowd of clients does not retry on the same tick.

We’ll use the exponential backoff calculator. You type the numbers. The schedule is calculated in the browser. The numbers can live in the URL. A pasted log is not stored there.

The sample, with no jitter

  1. Open the exponential backoff calculator.
  2. Click Load sample.
  3. Leave jitter on No jitter, and leave the first wait on Equals the base delay.

The sample is a base of 1000 ms, a multiplier of 2, a cap of 30000 ms, and 4 attempts. The page prints:

wait = min(cap, base * factor^attempt). attempt starts at 0, so the first wait is the base delay when factor^0 is 1. No random draw. The seed is ignored.
attempt 0, retry 1: 1000 ms (cumulative 1000 ms)
attempt 1, retry 2: 2000 ms (cumulative 3000 ms)
attempt 2, retry 3: 4000 ms (cumulative 7000 ms)
attempt 3, retry 4: 8000 ms (cumulative 15000 ms)

Attempt 0 means the exponent is 0, and 2 to the power 0 is 1, so the first wait is the base delay. Each later wait doubles. The cumulative column is the sum of the waits, not the clock time of a request that also spends time failing.

Switch First wait to Equals base times the multiplier. The exponent starts at 1. The same inputs print:

wait = min(cap, base * factor^attempt). attempt starts at 1, so the first wait is base * factor. That matches the AWS simulator, which increments n before the first sleep. No random draw. The seed is ignored.
attempt 1, retry 1: 2000 ms (cumulative 2000 ms)
attempt 2, retry 2: 4000 ms (cumulative 6000 ms)
attempt 3, retry 3: 8000 ms (cumulative 14000 ms)
attempt 4, retry 4: 16000 ms (cumulative 30000 ms)

That first-wait choice is the one in the AWS Architecture Blog simulator from Marc Brooker’s “Exponential Backoff And Jitter” (4 March 2015). The simulator hardcodes the multiplier as 2. This page uses the multiplier you type.

Drop the cap to 5000 ms, set the first wait back to the base delay, and keep 4 attempts:

wait = min(cap, base * factor^attempt). attempt starts at 0, so the first wait is the base delay when factor^0 is 1. No random draw. The seed is ignored.
attempt 0, retry 1: 1000 ms (cumulative 1000 ms)
attempt 1, retry 2: 2000 ms (cumulative 3000 ms)
attempt 2, retry 3: 4000 ms (cumulative 7000 ms)
attempt 3, retry 4: 5000 ms (cumulative 12000 ms, capped)
The cap cut 1 wait.

8000 is above the cap, so the fourth wait is 5000. The note counts how many waits the cap cut.

How this page builds a backoff scheduleYou set a base delay, a multiplier, a cap, and a jitter mode. Each wait is the capped exponential, or a draw inside it. Decorrelated jitter ignores the multiplier.NoneFullEqualDecorrelatedBase, multiplier,cap, attemptsJitter modemin of cap and basetimes factor to theattemptRandom from 0 up tothat valueHalf of it, plus arandom halfRandom from the baseup to 3 times theprevious waitTable of waits

The three jitter modes

Jitter uses a seed so the same inputs print the same waits on this page. The draws come from mulberry32. They are not Python’s random.uniform, and they are not the schedule of a particular SDK. Each jittered wait is rounded to 0.001 ms. The cumulative column adds those rounded waits.

Full jitter, seed 1, same base, multiplier, cap, and 4 attempts, first wait equal to the base:

temp = min(cap, base * factor^attempt); wait = random(0, temp). attempt starts at 0, so the first wait is the base delay when factor^0 is 1. random(min, max) is min + (max - min) * u, and u is in [0, 1) from mulberry32(seed).
attempt 0, retry 1: 627.074 ms (cumulative 627.074 ms)
attempt 1, retry 2: 5.471 ms (cumulative 632.545 ms)
attempt 2, retry 3: 2109.788 ms (cumulative 2742.333 ms)
attempt 3, retry 4: 7848.408 ms (cumulative 10590.741 ms)
Each wait is rounded to 0.001 ms. The cumulative column adds those rounded waits.

Full jitter draws from 0 up to the capped exponential. The range is half-open at the top. A wait can be almost 0, which is the point of this formula: it spreads the retries.

Equal jitter keeps half of that value and draws the other half:

temp = min(cap, base * factor^attempt); wait = temp / 2 + random(0, temp / 2). attempt starts at 0, so the first wait is the base delay when factor^0 is 1. random(min, max) is min + (max - min) * u, and u is in [0, 1) from mulberry32(seed).
attempt 0, retry 1: 813.537 ms (cumulative 813.537 ms)
attempt 1, retry 2: 1002.736 ms (cumulative 1816.273 ms)
attempt 2, retry 3: 3054.894 ms (cumulative 4871.167 ms)
attempt 3, retry 4: 7924.204 ms (cumulative 12795.371 ms)
Each wait is rounded to 0.001 ms. The cumulative column adds those rounded waits.

The shortest equal-jitter wait is half of the capped exponential. It does not collapse to a few milliseconds the way full jitter can.

Decorrelated jitter ignores the multiplier and the attempt index. The previous wait starts as the base delay. Each wait is a draw from the base up to three times the previous wait, then the cap:

wait = min(cap, random(base, previous * 3)), and previous starts at the base delay. The multiplier and the attempt index do not change this formula. random(min, max) is min + (max - min) * u, and u is in [0, 1) from mulberry32(seed).
attempt 0, retry 1: 2254.148 ms (cumulative 2254.148 ms)
attempt 1, retry 2: 1015.764 ms (cumulative 3269.912 ms)
attempt 2, retry 3: 2079.839 ms (cumulative 5349.751 ms)
attempt 3, retry 4: 6140.233 ms (cumulative 11489.984 ms)
Each wait is rounded to 0.001 ms. The cumulative column adds those rounded waits.

Change the seed and the jittered columns change. No jitter ignores the seed.

You can list up to 15 attempts. The base delay has to be greater than 0. The multiplier has to be at least 1. The cap has to be at least the base delay.

A 429 or a 503 is the usual reason to wait and try again. The HTTP status code list is the lookup. A webhook you are signing locally is a different job, and that is the webhook signature verifier.

Background jobs in Node.js with BullMQ is one place this schedule shows up in a queue. Making HTTP requests with Node is the call you would wrap. This page does not speak for BullMQ or for any SDK. It prints the formula above the table, and that formula is the one it used.

Try the Exponential Backoff Calculator

List the wait before each retry from a base delay, a multiplier, and a cap. Compare no jitter with full, equal, and decorrelated jitter.

Open the Exponential Backoff Calculator →

  • HTTP Status Codes: Search HTTP status codes 1xx–5xx with plain-English meanings and practical when-to-use notes.
  • Webhook Signature Verifier: Check Stripe, GitHub, Slack, Shopify, Paddle and Standard Webhooks signatures, and see why a valid webhook fails verification.

More tool tutorials →

Want me to talk about your product? You can sponsor this site.