Part 2 · System Design Core Concepts
Latency, Throughput & Why p99 Matters
An 80 ms average can hide a checkout that freezes for five seconds. Latency, throughput and Little's Law, why queues explode near full utilisation, and why at scale the p99 becomes what most users feel.
On this page
The Problem
Your dashboard says: "Average response time: 80 ms." Everything looks fine. But support tickets keep coming in: "The app is so slow!", "Checkout froze for 5 seconds!"
Both are true. The average hides a problem: most requests are fast, but a few are very slow, and your busiest, most valuable users meet those slow requests often.
To design fast systems you need the right words and the right numbers: latency (how long one request takes), throughput (how many requests are finished per second) and percentiles (numbers that show how slow the slowest requests are). We explain each one below.
The Core Idea
Think of a highway toll booth.
- Latency is how long one car takes to get through the booth: 30 seconds.
- Throughput is how many cars get through per hour: 120.
- Bandwidth is the maximum possible, the capacity: with 4 booths open, maybe 480 cars per hour.
These are related but different. Opening more booths raises throughput, but does not make any single car faster. A faster payment system (like FASTag, India's electronic toll system) lowers latency and raises throughput.
Now imagine 99 cars pass in 30 seconds each, but 1 car takes 20 minutes because the driver cannot find their wallet. The average looks fine, but everyone stuck behind that car is angry. Percentiles tell you about those slow cases.
How It Works
Latency
Latency is the time from sending a request to getting the response. For a web request, it has three parts:
- Networkdistance, round trips
- Queuewaiting behind others
- Service timecode, DB, other services
- Network time: the travel time between client and server. Distance matters (see lesson 1).
- Queue time: waiting in line because the server is busy with other requests.
- Service time: the real work: running code, asking the database, calling other services.
You will often hear response time used to mean the same thing.
Throughput
Throughput is how much work the system finishes in a unit of time. It is often measured as:
- RPS/QPS: requests or queries per second,
- TPS: transactions per second (a transaction is one complete business action, such as a payment),
- MB/s: data per second.
Bandwidth is the capacity (the size of the pipe). Throughput is what you really get through it. Difference in one line: bandwidth is what is possible, throughput is what happens.
Little's Law: the link between them
Little's Law is a simple formula that links the number of requests inside a system to the arrival rate and the time each request spends there. L is the average number of requests in the system. λ (lambda) is the arrival rate. W is the average time one request spends in the system.
Requests in the system at once = Arrival rate × Time each request spends L = λ × WExample: your API gets 500 requests per second, and each takes 40 ms (0.04 s).
L = 500 × 0.04 = 20 requests in flight at any momentSo you need at least about 20 worker threads or connections to keep up. (A worker thread is one unit of work that handles one request.) If the database slows down and requests now take 400 ms, you suddenly have 200 in flight. A pool of 50 threads cannot cope. Requests wait in a queue, and latency climbs even more.
This is how a slow database turns into a full outage.
Why latency explodes when servers get busy
When a server is lightly used, requests are handled right away. As it gets busier, requests start waiting in a queue. Utilisation means how busy the server is, as a percentage. The link between utilisation and latency is not a straight line:
Latency
│ ╱
│ ╱
│ ╱ ← near 100%: the queue grows without limit
│ __╱
│_______________________╱ ← headroom: run here (50–70%)
└──────────────────────────────────── Utilisation
0% 50% 70% 90% 100%At 50% busy, waits are short. At 90%, they are much longer. Near 100%, the queue grows without limit. This is why teams usually run servers at around 50–70% CPU, not 95%. The spare capacity (headroom) absorbs bursts, which are short sudden rises in traffic.
Think of a supermarket checkout. When the cashier is idle half the time, you walk right up. When the cashier is busy 95% of the time, one slow customer creates a long line.
Trading latency for throughput (and back)
- Batching (grouping work, such as sending 100 writes at once) raises throughput, but each item waits for the batch, so latency goes up.
- Caching (keeping a saved copy of an answer) lowers latency by skipping slow work.
- Parallel calls (calling three services at once instead of one after another) lower latency.
- More servers raise throughput, but do not make a single request faster.
Why averages lie
Latency is rarely spread out evenly. Most requests are fast, and a small group is very slow. This group is called the "long tail". The widget below lets you try it:
Chance the page waits on at least one p99-slow call: 10%. With fan-out, the p99 of each part becomes the typical experience of the whole.
One 5-second request can hide among 99 fast ones and barely move the average. Also, an average of 80 ms might mean nobody really saw 80 ms: half saw 20 ms and half saw 140 ms.
Percentiles
A percentile is a number that answers: "what latency were X% of requests faster than?"
- p50 (median): half the requests were faster than this. This is the "typical" user.
- p90: 90% were faster, so 1 in 10 was slower.
- p95: 1 in 20 was slower.
- p99: 1 in 100 was slower.
- p99.9: 1 in 1,000 was slower.
Example: 100 requests sorted from fastest to slowest.
- The 50th is p50 = 45 ms.
- The 99th is p99 = 1,200 ms.
"p99 = 1.2 s" means 1% of your requests take over 1.2 seconds. At 1 million requests a day, that is 10,000 slow experiences every day.
Why the tail matters more at scale
Users make many requests. Loading one page might trigger 50 API calls. If each call has a 1% chance of being slow, the chance that the page has at least one slow call is:
1 − 0.99^50 ≈ 40%So your "rare" p99 becomes something that 40% of page loads feel.
Fan-out makes it worse. Fan-out means one request is split into many requests to other servers. A search request might ask 100 servers in parallel and wait for all of them. Even if each server is slow only 1% of the time, the chance that at least one is slow is:
This is the key idea of Google's well-known paper "The Tail at Scale": in big systems, the rare slow case becomes the common case.
Your heaviest users feel it most. The customer with 5,000 items in their order history, or the seller with the biggest shop, often triggers the slowest queries. These are often your most valuable users.
Common causes of tail latency
- Garbage collection pauses. Garbage collection is when a language runtime (in Java, Go or Node.js, for example) stops to free memory that is no longer used.
- Queueing (waiting in line) during short bursts of traffic.
- Cache misses: the saved copy was not there, so the data had to come from the database.
- "Noisy neighbours": other programs on the same machine that use up the shared CPU, disk or network.
- Retries: sending a request again after a timeout (a timeout is when you stop waiting).
- Big users with big data, as described above.
- Cold starts: a new server or serverless function (code that the cloud runs on demand) that has to start up before it can answer.
Techniques to cut the tail
- Timeouts, so that one slow call cannot hang forever (Part 7).
- Caching hot data.
- Hedged requests: if a response has not arrived by the p95 time, send a second copy of the request to another server and use whichever answer comes first. Google describes this idea in its tail-latency paper.
- Keep servers below saturation (saturation means fully busy; keep the headroom from above).
- Paginate or limit heavy queries (return results in small pages), so that no single request does unlimited work.
Measuring percentiles correctly
- Record latencies in histograms. A histogram counts how many requests fell into each time range (for example 0–10 ms, 10–20 ms). Tools like Prometheus, Datadog and HdrHistogram support this.
- You cannot average percentiles. If server A has p99 = 100 ms and server B has p99 = 900 ms, the combined p99 is not 500 ms. Combine the raw histograms, then compute the percentile.
- Measure from the user's side too, not only the server's side. The network and the browser add time.
Trade-offs
- Improving p99 often costs more than improving the average (extra servers for headroom, hedged requests that add load, more caching).
- Batching improves throughput and cost, but hurts latency.
- Running servers "hot" (at high utilisation) saves money but makes latency jump up and down and makes outages more likely.
- Working on p99.9 may not be worth it for low-traffic internal tools. It matters most for high-traffic paths that users see, like search, checkout and login.
In the Real World
Amazon and the 99.9th percentile. Amazon's well-known Dynamo paper explains that its internal services set their speed targets at the 99.9th percentile, not the average. The reason is that the customers with the most activity often have the slowest requests, and these are exactly the customers that Amazon most wants to keep happy.
"Every 100 ms costs money." Early studies from Amazon and Google, which are often quoted, found that small increases in latency (about 100–500 ms) measurably reduced sales or searches. The exact numbers are old, but later studies agree with the lesson: users notice slowness, and they leave.
Google's "The Tail at Scale". Google engineers Jeff Dean and Luiz André Barroso showed how fan-out across many servers turns rare slowdowns into common ones, and described techniques like hedged requests to fight it. It is one of the most influential papers on performance.
Everyday apps. When a food-delivery app's restaurant list loads instantly but the "place order" button sometimes spins for several seconds, that is tail latency on one specific endpoint (one URL of the service). Averages across the whole app would not show it. A p99 for each endpoint would.
Interview Questions
Q1What is the difference between latency and throughput?
Latency is how long one request takes. Throughput is how many requests finish per second. They are linked but different. More servers raise throughput without making any single request faster. Batching raises throughput but makes each item wait longer.
Q2Why do we track p99 instead of the average?
Latency has a long tail. The average hides the slowest 1%, which at a million requests a day is 10,000 bad experiences. The average can also fall at a value that no request really had. p99 describes the experience of your unluckiest users, who are often your heaviest users.
Q3Use Little's Law: 2,000 requests per second, each takes 50 ms. How many are in flight?
L = λ × W = 2,000 × 0.05 = 100 requests at the same time, so you need at least about 100 worker slots or connections. If latency grows to 500 ms, this jumps to 1,000. This is how a slow dependency (a service you rely on) uses up all the pools and spreads into a full outage.
Q4Why not run servers at 95% CPU to save money?
Waiting time in the queue does not grow in a straight line with utilisation. Near full load, any burst builds a queue that takes a long time to clear. Tail latency then rises sharply, and small problems turn into outages. Headroom of around 30–50% (running at 50–70%) absorbs bursts.
Q5Can you average the p99 of two servers?
No. Percentiles cannot be averaged. Merge the underlying histograms (or the raw samples) and compute the percentile from the combined data.
Q6How would you reduce tail latency in a fan-out service?
Set timeouts, cache hot data, keep servers below saturation, limit the work per request, and use hedged requests. With hedged requests, if a reply is later than the p95, you send a duplicate to another replica (another copy of the service) and take whichever answer returns first.
Key Takeaways
- Latency = time per request. Throughput = requests per second. Bandwidth = maximum capacity.
- Little's Law (
L = λ × W) links them. A slower backend means more requests in flight and bigger pools needed. - Latency rises sharply as servers approach full utilisation, so keep headroom.
- Averages hide slow requests. Use percentiles: p50, p95, p99, p99.9.
- At scale, the tail becomes the common case because of multiple calls per page and fan-out. Measure with histograms, and never average percentiles.
Further Reading
- "The Tail at Scale" by Jeffrey Dean and Luiz André Barroso (Communications of the ACM, 2013)
- The Dynamo paper from Amazon (SOSP 2007), its section on service level agreements
- Gil Tene's talk "How NOT to Measure Latency"
- Systems Performance by Brendan Gregg (chapter 2, "Methodologies")
- The System Design Primer on GitHub (section "Latency vs throughput")
Published by Jainik · Last updated · How these lessons are made
Keep learning
Part of the study guide
Related series