Home › High-Level Design › Latency vs Throughput
L

Latency vs Throughput

Almost every system design interview turns on this one distinction, and most juniors blur the two together. Latency is how long one request takes. Throughput is how many requests you finish per second. They sound like the same idea, and they are related, but pushing one up often drags the other down. Knowing when to make that trade on purpose is what separates a confident answer from a shaky one.

High-Level DesignBeginner10 min read

If you remember five things

Everything below is the defense of these five calls.

  1. Two different numbers. Latency is one request's wait time (ms); throughput is finished requests per second (RPS). They move for different reasons.
  2. You cannot have both for free. Batching, queues, and bigger buffers buy throughput by spending latency. Picking which one to protect is the actual decision.
  3. Human waiting means latency. If a person stares at a spinner, protect latency. If a machine grinds a backlog, protect throughput.
  4. Find the bottleneck first. Throughput caps at your slowest shared resource. More app servers past that just pile up waiting requests and make latency worse.
  5. Always quote p99 under load. Averages lie and idle numbers lie. "50,000 RPS while p99 stays under 200ms" is the honest shape of an answer.

1The core idea#

Here is the mental model I use. Picture a coffee shop.

Latency is one customer's wait.

  • It is the clock from "I order" to "I have my drink."
  • A flat white that takes 90 seconds has a latency of 90 seconds, full stop.

Throughput is drinks out the door per minute, across all baristas.

  • Three baristas pulling shots in parallel might push out 20 drinks a minute.
  • Each individual drink still takes its own 90 seconds. Parallelism did not make any single drink faster.

They move for different reasons, and that is the whole lesson.

  • Add baristas and throughput climbs, while a single drink is exactly as slow as before.
  • Buy one faster machine and a single drink speeds up, while drinks-per-minute barely moves if one person is still making them.
The one sentence to internalize

Latency is about a single request's path. Throughput is about how many of those paths you can run at once. Fixing one does not automatically fix the other, and that gap is where every interesting trade-off lives.

In software terms:

  • Latency is milliseconds for one operation. "p99 read latency is 40ms" means 99 of 100 reads finish within 40 milliseconds.
  • Throughput is requests per second (RPS), queries per second (QPS), or sometimes bytes per second. "The service handles 12,000 RPS" is a throughput number.

One word that causes half the confusion: "fast."

  • A system can be "fast" because each request is snappy (low latency).
  • Or "fast" because it chews through a huge batch quickly (high throughput).
  • Nail down which one you mean before you say it in a room.

2How it works#

Trace a single request to see where latency comes from, then watch throughput stack on top of it.

flowchart LR A[Client] --> B[Load Balancer] B --> C[Service] C --> E[(Cache)] C --> D[(Database)]
The path one request walks. Latency is the sum of every hop on this line. Throughput is how many of these lines you can run side by side without them fighting over the same resource.

Latency is additive. Every hop adds to the bill.

  • Network time to reach the load balancer.
  • The load balancer picking a backend and forwarding.
  • The service doing its work: parsing, auth, business logic.
  • A cache lookup: a hit is under 1ms, a miss falls through.
  • On a miss, a database query: 5ms to 50ms depending on indexes and load.
  • The response traveling all the way back.

The only levers on latency: make a step faster or delete a step.

  • Five steps at 10ms each is 50ms no matter how beefy the servers are.
  • This is exactly why caching matters so much: a cache hit deletes the database round trip from the critical path.

Throughput is a different game: how many pipelines run at once without stepping on each other.

  • Add workers or servers so more requests run in parallel.
  • Batch, grouping many small operations into one trip. A database writing 1,000 rows in one batch does far more per second than one writing them singly, even though each row now waits longer.
  • Pipeline, starting request B while request A is still blocked on I/O.
This is the crux of the trade-off

Batching raises throughput and raises latency at the same time, because individual items sit in a buffer waiting for the batch to fill. A one-item-at-a-time path has low latency and wastes capacity. You are almost always choosing a point on that line, not escaping it.

Here is the time view of a batched write so the tension is visible:

sequenceDiagram participant C as Client participant S as Service participant Q as Buffer participant D as Database C->>S: write item S->>Q: enqueue Note over Q: wait to fill batch Q->>D: flush 500 items D-->>S: ack S-->>C: done
One client's write gets acknowledged only after the buffer fills and flushes. Great for throughput, worse for that one client's latency. The "wait to fill batch" note is the latency you traded away.

A worked example: the same service, two ways#

Numbers make this click, so run one all the way through. A service writes rows to a database. Each round trip to the database costs 5ms of latency, and the database can physically do at most 10,000 writes per second no matter how you send them.

Option A: one write per request.

  • Each client write is its own database trip, so a single write's latency is a clean 5ms.
  • A thread doing 5ms per trip manages 1 / 0.005 = 200 writes per second.
  • To reach the 10,000 writes/second ceiling you need 10,000 / 200 = 50 threads in parallel, each paying the full 5ms.
  • Scorecard: 5ms per write, 50 threads burned, capped at the database's 10,000 writes/second.

Option B: batch 500 writes per trip.

  • One trip now carries 500 rows. Call the write cost 10ms for the whole batch (5ms transfer plus a bit of server work).
  • Throughput per thread jumps to 500 / 0.010 = 50,000 writes/second, so one or two threads saturate the database.
  • But latency: an item arriving as a batch starts filling waits for 499 more items plus the flush. With a 20ms flush window its end-to-end latency is roughly 20ms + 10ms = 30ms, not 5ms.
Human waiting
Option A: one write per trip
Latency per write
5ms, clean and simple.
Throughput
200 writes/second per thread.
Cost to hit the ceiling
50 parallel threads to manage.
Pick it when
A person is waiting on each write.
Firehose
Option B: batch 500 per trip
Latency per write
~30ms with a 20ms flush window.
Throughput
50,000 writes/second per thread.
Cost to hit the ceiling
1 to 2 threads, far less concurrency.
Pick it when
Analytics ingest where 30ms is invisible.

Read the scorecard honestly. Same hardware. Batching bought a 6x throughput-per-thread gain and way less concurrency to manage, and it cost a 6x worse per-write latency (5ms to 30ms). If a human waits on each write, Option A wins. If it is a firehose of analytics events, Option B wins and the 30ms is invisible.

The gap the arithmetic hides

In Option B, if traffic goes quiet, a half-full buffer can park a single lonely item for the full 20ms flush interval with nobody else arriving. If you never bound that wait, a low-traffic window turns into mystery latency spikes. The fix (a time-based flush) is in the pitfalls, and interviewers love when you name this before they ask.

3Trade-offs#

The real decisions come down to a few recurring patterns.

Choice Helps Hurts When to pick it
Batching requests Throughput Latency per item Background jobs, analytics writes, bulk ingest
Serving each request alone Latency Throughput, cost efficiency User-facing clicks, checkout, search box
Adding a cache Latency on hits, throughput Freshness, memory cost, complexity Read-heavy, data that tolerates slight staleness
Adding more replicas Throughput Cost, consistency work Traffic spikes, read scaling
Compression Network throughput CPU and a bit of latency Large payloads over slow links

A few things worth saying out loud:

You do not optimize both at once for free.

  • When an interviewer says "improve this system," your first move is to ask which number they care about.
  • A fraud check on every card swipe needs low latency: a human is waiting.
  • A nightly report over a billion rows needs throughput: nobody cares if it takes 40 minutes as long as it finishes.

Queues decouple the two.

  • Put a queue between producers and consumers and the producer gets low latency (fire and forget).
  • Consumers grind through the backlog at whatever throughput they can manage.
  • The cost: the end-to-end result is now delayed and eventually consistent. This is the whole reason async architectures exist.

Throughput has a ceiling set by your slowest shared resource.

  • If every request hits one database that maxes out at 8,000 QPS, no pile of app servers gets you past 8,000.
  • Find the bottleneck first. Adding capacity anywhere else is wasted money.

Latency under load is the number that bites you.

  • A system that answers in 20ms idle can balloon to 2 seconds near its throughput ceiling, because requests start queuing.
  • Always talk about latency at a given load, never in a vacuum.
Pause before you read on: a service answers in 20ms with one user, but p99 is 2 seconds in production at peak. Nothing in the code changed. What happened?
Reveal the answer
The system is running near its throughput ceiling, so requests queue behind the bottleneck and wait their turn. The per-request work is still 20ms, but each request now spends most of its life sitting in line. This is why an idle benchmark is meaningless: latency and throughput are coupled through queuing, and the tail explodes exactly where you are busiest.

4Where it is used#

Concrete places this shows up.

Payment and checkout flows: latency wins.

  • A user staring at a spinner during checkout abandons the cart.
  • Keep the synchronous path short: validate, authorize, return.
  • Push anything that can wait (receipt email, analytics) to a queue and do it later.

Log and metrics pipelines: throughput wins.

  • You are shipping millions of events, and each event's individual latency does not matter.
  • Batch aggressively, flush every 5 seconds or every 10,000 events, and compress hard.
  • One pipeline might accept 500,000 events/second while each event sits in a buffer for a couple of seconds. Totally fine.

Search autocomplete: latency wins, brutally.

  • If suggestions do not appear in under about 100ms they feel broken and users ignore them.
  • Serve from memory, often a cache or an in-process trie, and never touch a slow backend on the hot path.

Video encoding or ML training: throughput wins.

  • You care about jobs finished per hour, not how long any single frame or batch takes.
  • Run huge parallel batches on GPUs and keep them saturated.

If a human is actively waiting, optimize latency. If a machine is grinding through a backlog, optimize throughput.

5Common pitfalls and gotchas#

Quoting averages instead of percentiles.

  • Average latency lies. If 99 requests take 10ms and one takes 3 seconds, your average is about 40ms, which sounds fine and hides a disaster.
  • Talk in percentiles: p50 (median), p95, p99. The p99 is what your unluckiest 1% feel, and at scale that 1% is a lot of people.
  • At 10,000 RPS, p99 is 100 slow requests every second. Say "p99" in a room and you sound like you have run production systems.

Confusing high throughput with low latency.

  • A system can have massive throughput and awful latency at once.
  • The batch pipeline is the classic: 500,000 events/second with 2 seconds of per-event latency.
  • Do not assume a "fast" system is fast in the way this problem needs.

Ignoring the tail under load.

  • Everything looks great in a demo with one user.
  • The interesting behavior is at 80% of capacity, where queues build and tail latency explodes.
  • Reason about the loaded state, not the idle one.

Forgetting that batching adds delay you must bound.

  • Flush only when the buffer is full and a quiet period parks items for a long time.
  • Always add a time-based flush too: "flush when full OR every 500ms," so latency has a ceiling.
  • This is the exact gap flagged in the worked example.

Thinking more servers always helps.

  • They help throughput only up to the bottleneck.
  • If the real limit is a single primary database or a lock, more app servers just pile up more waiting requests and make latency worse.

Measuring throughput without a latency budget.

  • It is easy to push throughput up by letting latency rot.
  • "We hit 50,000 RPS" means nothing if p99 was 9 seconds at that point.
  • The honest number is "50,000 RPS while keeping p99 under 200ms."

6How it shows up in interviews#

Interviewers probe this to see whether you treat systems as trade-offs and make deliberate choices instead of reaching for "just add more servers."

From the interviewer's chair

When I ask "how would you make this faster," I am watching for the pause. The candidate who asks "faster in latency or in throughput?" has already separated the two numbers in their head. The one who starts adding servers has told me they only know one lever, and it is often the wrong one for the problem.

Here is what the probing sounds like and how to handle it.

"How would you make this faster?"

  • A trap worth catching. Ask back: lower latency per request, or more requests per second?
  • Strong candidate pauses and clarifies. Weak one starts adding servers, which only helps throughput and might not touch the latency problem at all.

"What is your p99 target?"

  • They want a number tied to the use case.
  • Strong: "User-facing search, p99 under 150ms. Background indexing job, no latency target, I care about a million documents per hour."
  • Weak: "Fast as possible." Tells them nothing and shows no judgment.

"This endpoint is slow under load, what do you do?"

  • Strong answer walks the request path to find where time goes: CPU, slow query, lock, network. Then picks a fix matching the cause: cache the hot read, add an index, move work off the synchronous path into a queue.
  • Weak answer immediately says "scale horizontally" without knowing if the bottleneck is even scalable that way.

"Walk me through the trade-off of your design."

  • They want you to volunteer what you gave up.
  • Strong: "I batched the writes to hit our throughput target. The cost is each write takes up to 500ms longer, which is fine because this is an analytics path where nobody is waiting."
  • Naming the cost out loud is what earns the point.

Weak answer vs strong answer#

The prompt: "We have a write service capped around 10,000 writes per second on one database, and we need to ingest a lot more. What do you do?"

Candidate (weak): I would add more app servers and scale horizontally so we can handle more writes.

That fails twice. It never asks whether anyone is waiting on each write, and it throws servers at a bottleneck that is the single database, so the extra servers just queue up behind the same 10,000 writes/second ceiling and latency gets worse, not better.

Candidate (strong): First, is a human waiting on each write, or is this a firehose we just need to absorb? If it is ingest, I would batch, say 500 writes per database trip. From the math, that takes one thread from 200 writes per second to around 50,000, so one or two threads saturate the database instead of 50 threads. The cost is per-write latency goes from about 5ms to roughly 30ms with a 20ms flush window, which is fine for ingest. I would bound that with a flush-when-full-OR-every-500ms rule so a quiet period cannot park an item indefinitely, and I would hold myself to a target like 50,000 writes per second while keeping p99 under 200ms.

That picks the right metric, names the bottleneck, shows the arithmetic, and states the cost it accepted. That is the whole rubric in one breath.

The signal they are reading: can you pick the right metric for the problem, reason about the bottleneck, and state the trade-off plainly? Do that and you look like someone who has shipped and operated systems, not just read about them.

One last move for the whiteboard. Point at the synchronous path and say "this is my latency-critical path, I keep it short." Then point at the queue and say "this absorbs the throughput and runs async." That single gesture shows the interviewer you get it.

Follow-ups the interviewer will ask (and your answers)
"Why not just quote average latency?"
Averages hide the tail. Ninety-nine requests at 10ms and one at 3 seconds averages to about 40ms, which looks healthy and buries a disaster. I quote p50, p95, and p99, because p99 is what the unluckiest 1% feel, and at 10,000 RPS that is 100 slow requests every second.
"I added 10 more app servers and latency got worse. Why?"
The bottleneck was not the app tier. If every request funnels into one primary database or one lock, extra app servers just send more requests to wait in the same line, so queuing grows and latency climbs. Throughput caps at the slowest shared resource; you have to widen that, not the thing in front of it.
"Batching sped up ingest, but some writes now take seconds. What broke?"
An unbounded flush. If the buffer only flushes when full, a quiet period leaves items parked until enough traffic arrives to fill it. Fix it with a time-based flush: flush when full OR every 500ms, so per-item latency has a hard ceiling no matter how slow traffic gets.
"How do you decide between optimizing latency or throughput?"
Who is waiting. If a person is staring at the result (checkout, search, a card swipe), I protect latency and push everything deferrable onto a queue. If a machine is draining a backlog (logs, metrics, encoding, training), I protect throughput and batch hard, because per-item latency is invisible.
"Your benchmark says 20ms but production p99 is 2 seconds. Explain."
The benchmark was idle; production runs near the throughput ceiling. Per-request work is still 20ms, but requests now queue behind the bottleneck and spend most of their time waiting. That is why I always quote latency at a stated load, never in isolation.

What you can now explain in the room

  • The precise difference between latency (one request's ms) and throughput (finished requests per second), and why they move independently.
  • Why batching raises throughput and latency at the same time, with the Option A vs B arithmetic to prove it.
  • How a queue decouples producer latency from consumer throughput, and what consistency you pay for it.
  • Why throughput caps at the slowest shared resource, so more app servers past that only hurt latency.
  • Why you quote p99 under a stated load, and why averages and idle benchmarks lie.
  • How to pick the right metric per use case: human waiting means latency, machine grinding means throughput.

Next, try the System Design Question walkthrough on designing a URL shortener, where the read path is pure latency and the write path is a throughput problem, and you have to balance both in one design.

Get a prep plan built around your Latency vs Throughput interview

Tell us the role and your interview date. We will send back a dated, day by day plan. Free.

Thanks. Check your inbox, your Latency vs Throughput prep plan is on the way.