AI Infra Interviews logo
Napkin Math, Cost & Capacity / 02
easy★ EssentialNewOpenAIAnthropicBaseten

How big is the KV cache for Llama 3.1 70B at a 128k context?

Four numbers from the config file, one formula, and a per-sequence result that is a third of the model's own weights. Plus the mistake that makes the answer eight times too big.

Updated Sep 2026 · Grounded in real AI infrastructure interview loops and written to a senior-engineer editorial bar, with every number worked and every diagram hand-built.

TL;DR: KV bytes per token = 2 × layers × KV heads × head dim × bytes = 2 × 80 × 8 × 128 × 2 = 320 KB in bf16. At 131,072 tokens that is 320 KB × 131,072 ≈ 42 GB for one sequence, about a third of the 141 GB of weights, and it halves to 21 GB with an fp8 cache.

How to approach it

Ask which precision the cache is stored in, since fp8 KV is common and halves the answer. Then say the formula with every variable named before substituting, and say "two, for K and V" as the first factor so it is never dropped. Pull the four architecture numbers (80 layers, 8 KV heads, 128 head dimension, 2 bytes) and compute the per-token figure first, then multiply by context. Finish by placing the result against a card: "42 GB is more than half an H100, for one user."

A strong answer

A typical situation: a capacity plan uses the 64 attention heads instead of the 8 KV heads, comes out 8x too pessimistic, and concludes long context is unservable. The two fields sit next to each other in the config file.

Every token in a live sequence keeps one key and one value vector per KV head at every layer, so that later tokens can attend to it without recomputation. The size therefore depends on the attention shape, never on the parameter count. Llama 3.1 70B uses grouped-query attention: 64 query heads share 8 KV heads, and the cache stores only the 8.

inputs (from config.json):
  n_layers   = 80
  n_kv_heads = 8        (num_key_value_heads; the 64 is num_attention_heads, do not use it)
  d_head     = 128      (hidden 8192 ÷ 64 query heads)
  bytes      = 2        (bf16)

KV per token = 2 × n_layers × n_kv_heads × d_head × bytes
             = 2 × 80 × 8 × 128 × 2
             = 327,680 B = 320 KiB exactly (327.68 KB decimal; say KiB and mean it)

per sequence at 128k:
  context    = 131,072 tokens
  KV         = 327,680 × 131,072 = 4.29e10 B ≈ 42.9 GB

sanity: 42 GB is 30% of the 141 GB bf16 weights, and more than half of one 80 GB H100,
        so a single full-context user costs the fleet as much memory as a third of the model.

The number is usually needed in a capacity context, so carry it one step further. On an 8 × H100 node serving bf16 weights there is roughly 435 GB of usable memory after weights and a 10% reserve; at 42.9 GB per full-context sequence that is 10 concurrent 128k users. With an fp8 cache (bytes = 1) each sequence drops to 21.5 GB and the count doubles to 20. Move the weights to fp8 as well and the free budget rises to about 505 GB, or 23 users at 128k.

users at 128k on 8 × H100, bf16 weights:
  free = 8 × 80 × 0.9 − 141 = 435 GB
  bf16 KV: 435 ÷ 42.9 ≈ 10 sequences
  fp8 KV:  435 ÷ 21.5 ≈ 20 sequences

The MoE comparison is worth one sentence because it shows why the formula matters: Mixtral 8x7B has 47B parameters and the same 32-layer, 8-head, 128-dim shape as Llama 8B, so its cache is 128 KB per token, less than half the 70B's, despite the parameter count. DeepSeek-V3 with multi-head latent attention stores 61 × (512 + 64) × 2 ≈ 70 KB per token, a fifth of the 70B's, with 671B parameters. The cache is architecture arithmetic.

What reverses the "42 GB" answer is a different serving precision or a different model, never the batch size; the per-sequence cost is fixed, and batch only multiplies it. The KV cache sizing page carries the derivation for four models.

KV CACHE (drag through decoding)
Themodelwritesonetokenatatime
without cache10 ops
with cache4 ops
With the cache, each token's keys and values are computed once and reused. Without it, every step recomputes them for all prior tokens, so total work grows with the square of the sequence. At step 4 that is 2.5x more compute wasted.

The reversal condition: an MLA model, where the formula itself changes. DeepSeek-V3 stores a 576-wide latent per layer instead of full keys and values, so its cache is about 70 KB per token despite 671B parameters, and applying the GQA formula to it overestimates by more than three times. KV Cache Sizing works both shapes, and Attention Variants: MHA, GQA, MQA and MLA is where the layout difference comes from. Setting --kv-cache-dtype fp8 halves whichever number you land on, which is the cheapest lever here.

What interviewers probe next

  • "How would you cut it?" In order of effect: fp8 KV (halves it, no architecture change), paged allocation so reserved-but-unused context is not charged, prefix caching so a shared system prompt is stored once, and, at model selection time, fewer KV heads or MLA.
  • "What is it at 8k?" 320 KB × 8,192 = 2.6 GB. A batch of 64 such sequences is 168 GB, which is why short-context batches on the 70B still need a multi-card node.
  • "Does a longer context change the per-token cost?" No; the per-token figure is constant, and the sequence cost grows linearly. What grows faster is attention compute during prefill, which is a separate question.
  • "Why does GQA help here?" It divides the cache by the query-to-KV head ratio, 8 on this model, while keeping the query heads for quality.

Common mistakes

  • Using 64 heads instead of 8: 2 × 80 × 64 × 128 × 2 = 2.6 MB per token, 343 GB per 128k sequence, and a capacity plan eight times too pessimistic.
  • Dropping the factor of 2 and reporting 160 KB per token; the fix is to say "K and V" before anything else.
  • Multiplying by the parameter count somewhere, usually because the candidate remembers that "bigger models have bigger caches" and reaches for the wrong big number.
  • Reporting 40 GiB against a card quoted in GB, so the fit looks better than it is.

Key takeaways

  • KV per token = 2 × layers × KV heads × head dim × bytes; Llama 3.1 70B in bf16 is 320 KB.
  • 128k context: 42 GB per sequence in bf16, 21 GB in fp8. 8k context: 2.6 GB.
  • The KV-head count is 8, not 64; that one input is where the factor of eight hides.
  • On 8 × H100 with bf16 weights, about 10 full-context users fit; fp8 KV doubles it.
That one was free — and so are 10 answers per topic without an account. Signing in doubles that to 20, opens the Plus lessons in the courses, and remembers which topics you keep getting wrong.no card · Google sign-in · nothing to cancel
HOW DID IT GO?
0
READING SIGNED OUT

Signing in doubles your free answers, from 10 to 20 per topic, and the site starts remembering you: mastery per topic, bookmarks, and a next-focus recommendation. Free, no card.

Sign in free

The concepts behind this question

Ranked by how closely each one overlaps this question's topic, so the first card is the thing to read if the answer above moved too fast.

Foundational
🧮 Napkin Math & Capacity
KV Cache SizingThe KV cache is the memory that decides how many users a serving replica can hold and how long their context can be. Its size per token comes from four numbers in the model's config file (layers, KV heads, head dimension, bytes per element) and one formula; multiplied by context and concurrency it is the number every capacity plan is built on. This page derives it, works it for four models including an MLA one, and shows the two places candidates get it wrong by a factor of eight.
Foundational
🚀 Inference & Serving
The KV CacheThe KV cache stores each token's attention keys and values so decode never recomputes them, turning a quadratic cost into a linear one at the price of memory that grows with every token in every concurrent sequence. Its size, 128 KB per token for Llama 3.1 8B and 320 KB for 70B in bf16, is what caps concurrency and context on a given GPU, so it decides batch size, replica count and whether a model fits at all.
Foundational
🧮 Open Weights & Serving Engines
Multi-Head Latent Attention and Sparse IndexersGrouped-query attention shrank the KV cache by sharing key and value heads. Latent attention goes further by caching a single compressed vector per token per layer and reconstructing the heads on the fly, which cuts the cache by tens of times rather than by a small factor. On top of that, sparse indexers pick a few thousand relevant positions per query instead of attending to all of them, turning the quadratic term linear at long context. Both are now standard in open-weights models, and both change how a serving deployment is sized.
Advanced
🧮 Napkin Math & Capacity🔒 Premium
Bandwidth-Bound Decode ThroughputBecause decode reads every weight once per step, its speed is a division: memory bandwidth over bytes per step. That one formula gives single-stream tokens per second for any model on any card, the batch curve that flattens at the ridge point, the effect of quantization, and the point where the KV cache rather than the weights becomes the thing being read. This page derives it, works it for a 70B model on four accelerators, and shows how to read a vendor throughput claim against it.
UP NEXT ON YOUR JOURNEY
FEDITOR'S NOTE

The interviewer is listening for the KV-head count. A candidate who uses 64 query heads instead of 8 KV heads has not read a config file.

DISCUSSION · 0

No comments yet — be the first to share your approach.