Welcome back. In the previous lesson, you separated a streaming request’s TTFT, inter-token latency, end-to-end latency, and system throughput. Those metrics explain what users observe. This lesson examines a principal resource constraint behind decode throughput and long-context capacity: the key-value (KV) cache.
By the end, you will be able to calculate KV-cache memory in bytes or GiB from a model configuration and a serving workload, including the important distinction between query heads and KV heads. You will also be able to explain why a seemingly well-sized GPU can run out of memory as concurrent requests or context lengths grow.
Why decoding needs a cache
During autoregressive decode, each newly processed token attends to every earlier token in the active context. For every transformer layer, the current token produces a query , key , and value .
The current query is used once: it asks which earlier positions matter for this token. But the key and value for each earlier token will be needed again by every later token. Recomputing them at every decoding step would be wasteful. A KV cache stores those previously computed keys and values in device memory.
This is why the cache grows over the life of a request:
- Prefill processes the prompt and writes K and V tensors for its prompt tokens.
- Decode processes one new token at a time and appends one more K and V entry per layer.
- When a request completes, its cache can be released; until then, it occupies memory independently of other requests.
Watch the following short excerpt from The KV Cache: Memory Usage in Transformers by Efficient NLP. It connects the mechanics of one-token-at-a-time decoding to the storage formula we will derive.
The KV Cache: Memory Usage in Transformers
The KV Cache: Memory Usage in Transformers by Efficient NLP explains why keys and values, rather than queries, persist across decoding steps, then introduces the factors in the memory calculation.
Watch cache mechanics to see why prior K and V vectors are reused while each new query is transient. Then watch the formula and note the meaning of the factors for K and V, precision, layers, hidden width, sequence length, and batch size.
For a standard attention layer with a uniform sequence length, the cached tensors can be represented conceptually as:
where:
- is the number of active sequences, often called batch size;
- is the number of tokens currently retained per sequence;
- is the number of transformer layers;
- is the number of key-value heads;
- is the dimension of each head;
- is the number of bytes used per cached scalar.
There are two tensors, and , at every layer. Counting elements in these tensors gives the core formula:
The result is in bytes.
The factor of is non-negotiable: there is one cache for keys and a separate cache for values. The other factors correspond directly to the tensor dimensions. If any one of batch size, sequence length, layer count, KV-head count, head dimension, or bytes per value doubles, the cache memory doubles.
The formula in its common hidden-size form
For conventional multi-head attention, each query head has its own corresponding key and value head:
The attention width is then:
So, for conventional multi-head attention, the formula is commonly written as:
This is the compact form you will often see in model-serving documentation. It is correct only when the model uses one KV head for every query head.
NVIDIA’s Mastering LLM Techniques: Inference Optimization gives this standard formula and a Llama 2 7B example.
Mastering LLM Techniques: Inference Optimization
In the “LLM memory requirement” section, NVIDIA distinguishes fixed model-weight memory from workload-dependent KV-cache memory and derives the standard cache-size calculation.
Read from the paragraph beginning the per-token derivation. Then continue through the total-cache formula and Llama 2 7B example, ending at the scaling discussion. Focus on why batch size and sequence length multiply the cache requirement rather than being alternative costs.
Precision is a byte multiplier
For planning purposes, use the representation of the KV cache, not automatically the representation of the model weights:
| KV-cache representation | Bytes per cached value, |
|---|---|
| FP32 | 4 bytes |
| FP16 | 2 bytes |
| BF16 | 2 bytes |
| FP8 or 8-bit integer format | 1 byte |
For example, a model could have 4-bit weights but an FP16 KV cache. Its weights and cache must then be calculated separately using their respective byte sizes. The next lesson will examine the practical trade-offs of cache quantization; for this lesson, treat precision as a direct storage multiplier.
Sequence length means tokens resident in the cache
For capacity planning, includes both prompt tokens and generated tokens that remain active:
A conservative limit uses the largest final sequence the service permits:
Implementations may differ by one token depending on when sampling and cache insertion occur. That detail does not materially affect capacity planning. Reserving for the permitted total context is safer than relying on an average response length.
Worked calculation: Llama 2 7B at 4,096 tokens
Consider the conventional multi-head-attention Llama 2 7B example in FP16:
| Parameter | Value |
|---|---|
| Active sequences, | 1 |
| Context length, | 4,096 tokens |
| Layers, | 32 |
| KV heads, | 32 |
| Head dimension, | 128 |
| KV precision, | 2 bytes |
First compute the memory added by one token for one sequence:
Now multiply by the 4,096 cached token positions:
So one 4,096-token active sequence needs about 2 GiB of KV cache before accounting for model weights, CUDA runtime allocations, attention workspaces, temporary activations, and allocator fragmentation.
With a homogeneous batch of eight such sequences:
The cache grows at a rate of:
across that batch. In other words, if all eight requests remain active and their contexts each grow by one token, the aggregate cache grows by about 4 MiB.

The chart makes the serving consequence visible. At batch size 1, the cache is smaller than the model weights. At batch size 8, it is already larger. At batch size 64, the 128 GiB cache requirement exceeds the memory of a typical single GPU by a wide margin.
Be precise about units when reporting the result:
- The formula produces bytes.
- Dividing by yields GiB.
- Documentation and charts sometimes write “GB” while using values that are effectively GiB. For a capacity decision, state which convention you used rather than treating the labels as interchangeable.
MHA, GQA, and MQA: use KV heads, not always attention heads
The hidden-size shortcut is useful, but modern models often use grouped-query attention (GQA) or multi-query attention (MQA). In these architectures, many query heads share fewer KV heads.
The general formula remains:
What changes is .
- Multi-head attention (MHA): .
- Grouped-query attention (GQA): .
- Multi-query attention (MQA): .

The cache-saving ratio relative to MHA is:
For instance, if a model has 32 query heads and 8 KV heads, GQA uses one quarter of the MHA cache:
This distinction is an interview-critical configuration-reading habit:
num_attention_headsusually gives .num_key_value_headsgives .- If
num_key_value_headsis absent in a conventional MHA configuration, use the attention-head count. - Do not blindly substitute
hidden_sizefor in a GQA or MQA model. That would overestimate cache memory.
Worked calculation: a GQA model
Suppose an FP16 model has:
| Parameter | Value |
|---|---|
| Batch size, | 16 |
| Context length, | 8,192 tokens |
| Layers, | 32 |
| Query heads, | 32 |
| KV heads, | 8 |
| Head dimension, | 128 |
| KV precision, | 2 bytes |
First calculate the cache added by one token from one sequence:
There are:
active token positions. Therefore:
Now compare this with the hypothetical MHA version of the same model. It would use 32 KV heads rather than 8, so its KV cache would be:
GQA saves 48 GiB for this workload. It also reduces the amount of cached state that decode must repeatedly read, which is significant because autoregressive decode is often constrained by memory movement rather than raw floating-point compute.
From a uniform batch to real serving traffic
The simple formula assumes every active sequence has the same cached length . In a real serving engine, requests usually have different prompt lengths and may be at different stages of generation.
For active requests with current cached lengths , calculate the live payload as:
This is the same principle: count the total number of active token positions, then multiply by the cache cost per position.
For example, if the per-token KV-cache cost is 128 KiB and three active requests have 1,000, 3,000, and 6,000 cached tokens, then their total token positions are:
Their cache payload is:
approximately.
There are two meanings of “memory required” that should not be conflated:
- Live cache payload is the memory corresponding to tokens actually stored now. The heterogeneous formula estimates this quantity.
- Allocated capacity is what an engine may reserve in blocks, pages, or fixed per-request buffers. It can be larger because of maximum-length reservations, block granularity, padding, and fragmentation.
When diagnosing an out-of-memory event, first establish which one you are seeing. A service may have moderate live token usage but still fail because its allocator reserved capacity inefficiently or because too little memory remained after weights and runtime overhead.
A practical capacity calculation
Let mean memory available for KV cache after reserving memory for:
- model weights;
- runtime and CUDA context allocations;
- temporary workspaces;
- non-KV activations and implementation overhead;
- a safety margin for variation and fragmentation.
For a homogeneous workload, an upper-bound batch estimate is:
Treat this as a planning bound, not a production guarantee. A configuration that mathematically consumes every remaining byte is not deployable safely. The important systems-design inference is that maximum concurrency is not determined by parameter count alone. It depends strongly on:
- maximum prompt and output lengths;
- cache precision;
- attention design, especially KV-head count;
- the amount of memory retained for non-cache work.
This explains why a long-context serving endpoint may require more GPUs even if its model weights fit comfortably on one GPU.
Key takeaways
The KV cache stores the key and value vectors for every retained token, at every transformer layer, so they do not need to be recomputed during autoregressive decode.
For a uniform batch, calculate its payload with:
Remember the interpretation of each factor:
- accounts for both keys and values.
- and make cache use grow linearly with active concurrency and retained context.
- reflects storing K and V at every transformer layer.
- Use KV-head count, , not always query-head count.
- is the bytes per cached value and can differ from weight precision.
For MHA, , which yields the familiar hidden-size formula. For GQA and MQA, use the explicit KV-head formula; this is where substantial cache savings come from.
Next, you will evaluate weight and KV-cache quantization as a capacity and bandwidth lever, including why lower precision can increase concurrency but may also affect latency and model quality.
Can't find a good explanation? Sign up and we'll make it for you
Sign up