Throughput Planner
Target request rate, prompt and output lengths into required capacity, by converting each request into GPU-seconds of prefill and decode.
0.472 GPU-seconds per request × 10.00 req/s at peak = 4.72 GPUs of work, run at 70% utilisation.
- Prefill time per request
- 222 ms
- Decode time per request
- 250 ms
- GPU-seconds per request
- 0.472
- Peak request rate
- 10.00 req/s
- Tokens/s at peak
- 24,000 tok/s
- GPU-equivalents of work at peak
- 4.72
- GPUs at target utilisation
- 7
- Actual utilisation at that count
- 67.46%
- Sustainable average rate
- 5.19 req/s
Capacity is a time budget, not a token budget
GPU-seconds per request = input ÷ prefill rate + output ÷ decode rate
GPUs = ⌈ (requests/s × peak factor × GPU-seconds) ÷ target utilisation ⌉
The instinct is to add up tokens per second and divide, but input and output tokens are not the same unit of work. Prefill processes the whole prompt in parallel and is compute-bound, so a GPU chews through thousands of input tokens a second. Decode emits one token per step per sequence and is bandwidth-bound, and its aggregate rate is far lower. Converting both into seconds of GPU time first is what makes them addable, and it is why a retrieval-heavy workload with short answers sizes completely differently from a long-generation one.
Two multipliers do most of the damage in real plans. The first is the peak factor: traffic that averages five requests a second does not arrive five per second, and a fleet sized for the average is permanently behind during the busy hour. The second is target utilisation. Queueing delay is not linear in load — it rises gently to about 70%, then sharply, and at 95% a small burst produces a wait nobody budgeted for. Planning to 70% is not waste; it is the cost of predictable latency.
What this deliberately does not do is guess your throughput numbers. Measure them on your engine, your quantisation, your batch size and your real context length, then come back — the answer is only as good as those two fields.