Serving
Batch throughput
How many people one GPU can serve at once before the experience gets bad. Weights are read once per decode step and the KV cache is read per sequence, so batching multiplies total throughput while barely touching per-user speed — until the cache runs out of room.
—
Concurrent users
—
Total throughput
—tok/s
Per user
—tok/s
Cost / M tokens
—
Where the memory goes
0
Batch ladder
| Concurrent | Per user | Total | KV used | Bound by | $ / M tok |
|---|
What this assumes
- Weights once, KV per sequence. A decode step reads the active weights a single time no matter how many sequences are in flight, then reads each sequence's cache. That asymmetry is the whole reason batching works, and why long contexts destroy it — at 32k the cache dwarfs the weights and the per-step read scales with users again.
- Concurrency is usually memory-limited, not compute-limited. On most cards you run out of room for KV caches long before you run out of FLOPs. The ladder marks which constraint binds at each level.
-
10% of VRAM is held back. vLLM defaults
gpu_memory_utilizationto 0.90, and a paged allocator needs slack to avoid preemption thrash under bursty arrival. Sizing to 100% of free memory builds a server that OOMs in its first bad minute. - This is steady-state throughput, not p95 latency. It assumes every slot is full and arrival is smooth. Real traffic is bursty, queueing adds delay before a request starts decoding, and prefill competes with decode for the same GPU. Size for less than this.
- Decode MFU is 25%. Batched decode GEMMs are skinny — batch × hidden against hidden × hidden — so they never reach the arithmetic intensity a long prompt does, even at large batch.