What it means
Jitter is randomness you add on purpose. In distributed systems it almost always means randomising a delay: instead of every client waiting exactly two seconds, each waits somewhere between zero and four, or between one and three.
The word is borrowed from signal processing, where jitter is unwanted timing variation. In systems work it is the opposite: a small, deliberate imperfection that stops a population of independent clients from behaving as one very large client.
The problem, with numbers
Take five thousand clients hitting the same API. At time T the service degrades and every one of them receives an error. All five thousand start the same retry policy, which is textbook exponential backoff: wait one second, then two, then four.
At T plus one second, five thousand requests arrive inside the same second. They fail. At T plus three seconds, five thousand more. Then at T plus seven. The retry traffic is not a flood, it is a series of spikes, and every spike is as tall as the burst that broke the service in the first place. Backoff has reduced the average load and left the peak untouched, and peak is what saturates a server.
Now spread the same five thousand retries uniformly across an eight-second window. The expected peak is 625 requests per second rather than 5,000 in one second: an eight-fold reduction, from one line of code. That is the entire argument. Jitter costs nothing, changes no architecture, and removes the sharpest edge of a retry storm.
The pattern has a name outside retries too: the thundering herd, where many waiters wake simultaneously for one resource. Ethernet has randomised its binary exponential backoff since the original CSMA/CD design, for precisely this reason. The idea long predates HTTP.
The four strategies
The canonical formulation comes from an AWS Architecture Blog post by Marc Brooker, "Exponential Backoff and Jitter", which simulated the variants against a contended resource and found that adding jitter reduced both total work and time to completion compared with plain backoff. The table below works each one at the same point in the curve, so the shapes are directly comparable: base 500 ms, multiplier 2, fourth attempt, undecorated delay 4.000 seconds.
The practical distinction is the floor. Full jitter can return almost zero, which is fine when the failure was a blip and dangerous when the server is saturated, because a fraction of your clients will retry immediately. Equal jitter guarantees at least half the computed delay while still spreading the other half. Decorrelated jitter grows from the previous actual sleep rather than from the attempt number, so a long-lived client keeps widening its spread instead of resetting to the same ladder.
Retry-After is a floor, and jitter goes above it
When the server tells you how long to wait, obey it and then add randomness on top. Never inside.
wait = retry_after + random(0, min(retry_after, 5 seconds))
A client that jitters downward from a stated wait sends a request the server has already promised to refuse. On a metered API that refusal is not free: it still counts against the ceiling it was refused by. See Retry-After for the header itself and exponential backoff for the curve underneath it.
Everywhere else jitter belongs
Retries are the famous case. They are not the most common one.
Scheduled jobs. If every tenant's nightly sync is configured for 00:00, you have built a load test that runs once a day. This one is concrete on a metered API: the daily quota on the Pinlyx Data API resets at 00:00 UTC, which is exactly the moment every quota-aware client is most tempted to start its batch. Spread the start across the first ten minutes and the entire population stops competing for the same first minute.
Cache expiry. A thousand keys written in the same deploy with the same TTL expire in the same second, and every subsequent miss stampedes the origin at once. Jitter the TTL: ttl = base_ttl * (1 + random(-0.1, 0.1)) turns a cliff into a slope.
Reconnect loops. A WebSocket or SignalR server that restarts disconnects every client in the same instant, and an un-jittered reconnect policy brings them all back in the same instant too, against a process that has not finished warming up. This is one of the few cases where the reconnect storm can prevent the recovery it is trying to detect.
Token refresh. Every instance refreshing its credential at exactly expiry minus 60 seconds produces a synchronised burst against the auth service, and they stay synchronised forever because the next expiry is the same for all of them.
Health checks and polling. Same shape, lower stakes, and trivially fixed by randomising the first interval.
Where jitter is the wrong tool
Randomness is not free everywhere. Three cases where adding it is a mistake:
- Inside a user-facing latency budget. Turning a predictable 200 ms into a random 0 to 400 ms makes the p99 worse and the experience feel unreliable, without spreading any load that mattered.
- When ordering matters. Randomised delays reorder work. If two operations on the same record must land in sequence, jitter the batch, not the individual items.
- As a substitute for a concurrency limit. Jitter spreads a burst over time; it does not cap how much work is in flight. If your client can open two hundred sockets, jitter merely staggers when it does so.
Related concepts
- Exponential backoff: the curve jitter is applied to.
- Retry-After: the server's floor, which jitter is added above.
- Rate limit: the ceiling whose reset boundary is the most synchronising clock in the system.
- Webhook replay: bulk re-delivery is another place a fleet can be triggered in unison.
- Flood wait: the same dynamic on Telegram, where synchronised sending is what triggers the wait in the first place.
How Pinlyx handles it
Pacing with deliberate variation is built into the sending side of the product, not just the API client: outbound messaging enforces a minimum interval between sends per account and varies it rather than firing on a metronome, because a perfectly regular send cadence is itself a signal platforms look for. On the API side, every 429 carries a Retry-After so clients have a real floor to jitter above, and the two 429 codes are separated so nobody jitters around a wait that will not clear until midnight.