Size in tokens, not TFLOPS
The useful line item is HBM remaining after weights, divided by bytes per token — a figure a facility can commit to and a customer can be sold.
INSIGHTInference economics
In large-language-model serving the binding constraint is usually memory, not arithmetic. The key-value (KV) cache grows linearly with context length and with the number of concurrent sequences, and — unlike model weights — it is not shared across a batch. On an eight-GPU H200 node serving a Llama-3-70B-shaped model in FP16, the cache overtakes the model itself at roughly 427,000 tokens of live context, and the attention step that reads it runs at about 4% of the accelerator's FLOP-per-byte ridge point. Capacity planning that counts TFLOPS will size the wrong machine.
PUBLISHED LAST VERIFIED BY JOSEF ELIMELECHREVIEWED PODOS AI ENGINEERING
What you need to know
2 x layers x kv_heads x head_dim x bytes, times context, times concurrency. No benchmark required — published model shapes give an exact answer.
Batching reads the weights once for the whole batch. Every sequence still reads its own cache, in full, on every step.
HBM left after the weights, divided by bytes per token, is the number of sequences a node can hold. Clock speed does not enter into it.
Grouped-query attention, latent attention, and KV quantization all buy the same thing: fewer bytes per cached token.
The short answer
Plain English first
A transformer generates one token at a time, and every new token attends to every token before it. Rather than recompute the representation of the whole conversation on each step, the server keeps two vectors per token, per layer — a key and a value — and re-reads them. That store is the KV cache. It is not optional, and its size is not a matter of tuning; it is arithmetic:
bytes per token = 2 (K and V) × layers × kv_heads × head_dim × bytes_per_element
cache bytes = bytes_per_token × context_length × concurrent_sequences
Nothing in that expression is a benchmark. Put a published model shape into it and the answer is exact. Meta publishes the shapes for Llama 3: 32 / 80 / 126 layers at 8B / 70B / 405B, model dimensions of 4,096 / 8,192 / 16,384, 32 / 64 / 128 attention heads, and — critically — 8 key/value heads at every size.[5] Head dimension is model dimension over attention heads, which is 128 in all three cases.
Fig. 1 · Derived from [5]
Head dim 128, two bytes per element. The last column is the counterfactual if the same shape used one KV head per query head — the reason grouped-query attention exists at all.
| Shape | Layers | Q heads | KV heads | FP16 KV per token | Same shape, full MHA |
|---|---|---|---|---|---|
| 8B | 32 | 32 | 8 | 128 KiB | 512 KiB |
| 70B | 80 | 64 | 8 | 320 KiB | 2,560 KiB |
| 405B | 126 | 128 | 8 | 504 KiB | 8,064 KiB |
The worked calculation
Shazeer named the underlying problem in 2019: incremental inference is often slow "due to the memory-bandwidth cost of repeatedly loading the large keys and values tensors," and sharing one KV head across all query heads shrinks those tensors directly.[1] GQA generalised that to an intermediate number of KV heads, reaching quality close to full multi-head attention at multi-query speed.[2] Pope et al. quantified the payoff in the currency that matters here: the lower memory requirement of multiquery attention enabled scaling up to 32× larger context lengths.[3]
So take a 70B-shaped model on a node of eight H200 SXM GPUs. NVIDIA lists 141GB of HBM3e and 4.8TB/s per GPU.[6] The assumptions below are the ones worth arguing with.
Fig. 2 · KV cache, 70B shape, FP16
Emphasised cells exceed the 815 GiB node budget derived above. They do not fit, at any clock speed.
| Context length | 1 sequence | 8 sequences | 32 sequences | 128 sequences |
|---|---|---|---|---|
| 4,096 (4K) | 1.25 GiB | 10 GiB | 40 GiB | 160 GiB |
| 32,768 (32K) | 10 GiB | 80 GiB | 320 GiB | 1,280 GiB |
| 131,072 (128K) | 40 GiB | 320 GiB | 1,280 GiB | 5,120 GiB |
Reading the table
First, the concurrency ceiling: 815 GiB divided by 40 GiB per full-context sequence is about 20 concurrent 128K-token sequences on that node — 81 at 32K, roughly 650 at 4K. Second, the crossover point: at 320 KiB per token, the cache equals the 130 GiB of FP16 weights at about 427,000 tokens of live context. That is only 3.3 sequences at 128K, 13 at 32K, or 104 at 4K. Past that line the cache — not the model — is the larger tenant of the node's HBM. Third, the shape of the growth: the cache is linear in context and linear in concurrency, so it is quadratic in "serve twice as many users at twice the context."
These are ceilings, not achievable operating points. Real allocators do worse: the vLLM authors measured that "only 20.4% - 38.2% of the KV cache memory is used to store the actual token states in the existing systems" before paged allocation, the rest lost to internal and external fragmentation.[4] Paged management recovers most of that headroom, but it recovers it against the same hard ceiling — it does not raise it.
The arithmetic intensity of decode attention is simply the grouped-query ratio. Head dimension cancels. Context length cancels. Layer count cancels. Batch size cancels.
8
FLOP per byte · Llama 3 shape
The derivation
The standard answer to a memory-bandwidth problem is to batch: read the weights once and amortise them across many sequences. That works for the weights. It does nothing for the cache — every sequence has its own, and every sequence reads all of it, every step. Batching multiplies KV traffic instead of amortising it. Per layer, per sequence, per generated token, over a context of length L:
bytes read = 2 × kv_heads × head_dim × L × 2 B = 4 · kv_heads · head_dim · L
FLOPs (QKᵀ then AV) = 2 × (2 · q_heads · head_dim · L) = 4 · q_heads · head_dim · L
intensity = FLOPs / bytes = q_heads / kv_heads
Compare that to the ridge point of the hardware. NVIDIA lists 1,979 FP16 tensor-core TFLOPS for H200 with sparsity — roughly 990 dense — against 4.8TB/s, giving about 206 FLOP per byte before the tensor cores are saturated.[6]
Fig. 3 · Derived, not measured
A 64-query-head shape against the 206 FLOP/byte ridge point. Group sizes from [1][2][5]; ridge point from [6].
| Scheme | KV heads | FLOP per byte | Share of the ridge point |
|---|---|---|---|
| MHA | 64 | 1 | 0.5% |
| GQA 8:1 (Llama 3 shape) | 8 | 8 | 3.9% |
| MQA | 1 | 64 | 31% |
Grouped-query attention moves a 70B-shaped model eight times closer to the ridge and still leaves it running attention at about 4% of the machine's arithmetic capability. This is the real content of the claim that inference is memory-bound: not a benchmark result, but a structural property of the operation. Which is also why the interesting architectural work attacks bytes rather than operations — DeepSeek-V2's multi-head latent attention reports a 93.3% reduction in KV cache by compressing keys and values into a latent vector,[9] and TurboQuant reports quality-neutral KV quantization at about 3.5 bits per channel, with marginal degradation at 2.5.[10] Both buy the same thing: bytes.
Consequences
If the constraint is memory, then the capacity model, the purchasing decision, and the telemetry all move.
The useful line item is HBM remaining after weights, divided by bytes per token — a figure a facility can commit to and a customer can be sold.
Moving a product from 32K to 128K does not cost 4× the compute. On the numbers above it costs 4× the cache and cuts concurrency per node by the same factor.
Tensor-parallel serving splits the cache across accelerators sharing one high-bandwidth GPU-to-GPU fabric, so the ceiling is set by the NVLink domain — a rack-scale quantity in designs where 72 GPUs act as one domain.[8]
Prefill is compute-bound and interleaves with decode on the same silicon. The thermal and electrical design still has to carry nameplate draw.
Cache pressure, not GPU utilization, is what precedes queueing and eviction in a serving fleet — and a utilization dashboard cannot see it.
Two models of the same parameter count can differ eightfold in bytes per token. The KV shape, not the parameter count, is what a capacity model needs.
In the product
The infrastructure consequence is unglamorous: the memory you can power and cool inside one coherent GPU-to-GPU domain[7][8] sets the inference capacity of a site. That is the design problem behind high-density GPU infrastructure — packing accelerators tightly enough to share one fabric, then removing the heat that packing creates through direct-to-chip liquid cooling and feeding it with a power architecture sized for the worst-case phase.
Each PODOS Pod is designed as a standardized 1 MW building block and designed for 128 GPUs — a unit sized so that power, cooling and the accelerator domain scale together rather than being renegotiated per site. To sketch capacity against your own workload, start with the configurator; unfamiliar terms are defined in the AI infrastructure glossary.
Honest limits
The calculations above are arithmetic on published specifications. No hardware was measured for this article, and the following limits are load-bearing.
Send the model shape, the context window, and the concurrency you need to serve. Engineering will work the memory arithmetic back to a unit count.