Capacity you store and capacity you pay for can be two different numbers.
In 2024 the reliable way to make a language model smarter was to make everything bigger — and every bigger number landed on the same bill: more compute per token to train it, more memory per token to serve it. DeepSeek-V2 is a bet that those couplings can be cut without giving up quality.
It cuts two of them. DeepSeekMoE stores 236B parameters but routes each token through only 21B of them, so training compute stops tracking total size. Multi-head Latent Attention (MLA) replaces attention's per-head memory of past tokens with one small compressed note per token, so serving a 128K-token context stops tracking head count. The paper's own ablations show the compressed attention scoring higher than the standard kind — the discount comes with no quality surcharge.
Two decouplings, one model: pay for 21B while storing 236B, and remember 128K tokens on a sliver of one GPU.
The memory bill
What this model promises, and what standard attention would charge for it
Step 1 · The black box
A 236B model that keeps most of itself asleep.
Here is the whole machine before we open it. You paste in a 300-page annual report — roughly 128K tokens, the word-pieces a model actually reads — and ask: “What changed in the risk section this year?” The model writes an answer, one token at a time, and every token it writes has to look back across everything you pasted. This report question is our running example; we will keep billing it, compressing it, and re-billing it for the rest of the page.
The paper leads with three numbers, all measured against DeepSeek 67B — the same lab's earlier, conventional (dense — every parameter works on every token) model: 42.5% cheaper to train, a 93.3% smaller KV cache, and 5.76× higher peak generation throughput. Notice what kind of numbers these are. Not accuracy records — prices. This is an economics paper wearing an architecture paper's clothes, and the two inventions inside it are both cost-cutting machines.
One of those terms needs its own step. The KV cache is the memory a model burns while writing, and it is the quiet villain of long-context AI. Let's price it properly before we admire anything.
From the abstract: “DeepSeek-V2 … comprises 236B total parameters, of which 21B are activated for each token, and supports a context length of 128K tokens.” Weights were released openly, plus a 15.7B little sibling (V2-Lite) for people who want to poke the architecture on one GPU.
Step 2 · The villain
Generation doesn't run out of compute — it runs out of memory.
Step 1 promised a model that reads your whole report and answers cheaply. Before trusting any of the discounts, let's compute what “reads your whole report” costs a standard Transformer at answer time.
You already know the attention recipe from the Transformer: each token makes a query, compares it against every other token's key, and uses the resulting weights to mix their values. During generation there's a crucial asymmetry: the keys and values of tokens already read never change. Recomputing them for every new token would be absurd, so every serving system stores them — that store is the KV cache.
Now the bill, with DeepSeek-V2's own shapes. Its attention has 128 heads, each 128 dimensions wide, across 60 layers. Cached the standard multi-head way, one token deposits a key and a value per head per layer:
At two bytes per number (BF16) that's 3.93 MB for a single token. Multiply by the report — 131,072 tokens — and one conversation holds ≈ 515 GB of cache. An entire 8-GPU H800 node carries 640 GB, and the model's weights already want most of it. The picture below is that arithmetic drawn out; watch the bag on the right fill up.
And memory is throughput. A GPU serves many users by batching their conversations; the cache decides how many fit. Halve the cache and you can roughly double the batch — which is why this page keeps talking about memory when the headline you may care about is tokens per second.
The KV cache grows as context × layers × heads × head-dim, and it throttles batch size — which is throughput. Whoever shrinks the cache without hurting quality wins on both context length and serving cost at once.
Accounting note: we price every cached number at 2 bytes (BF16) throughout. The paper's Table 1 counts elements, precision aside, and the deployed system squeezes each element to ~6 bits — we come back to that in Step 8 when the 93.3% headline gets audited.
Step 3 · The surgery map
Still a Transformer — with two organs swapped out.
The bill is real: ≈ 515 GB of cache for one 128K conversation, on hardware that carries 640 GB per node. DeepSeek-V2's response is not one clever trick but two separate surgeries.
Zoom into the box from Step 1 and you find nothing exotic: 60 identical Transformer blocks, each one an attention module followed by a feed-forward network (FFN), with normalization and residual connections in the usual places. The paper explicitly keeps every “tiny detail” identical to DeepSeek 67B. The novelty is concentrated in exactly two places, and the diagram below marks both — attention is replaced by MLA, and the FFN by DeepSeekMoE.
The two surgeries split the two bills between them. MLA attacks the serving bill — the 515 GB bag from Step 2 — and it is the invention this paper is remembered for, so Part B takes it apart slowly. DeepSeekMoE attacks the training bill — how a model stores 236B parameters while charging 21B per token — and Part C walks it at a brisker pace. If you came here from our DeepSeek-V3 page: this is the origin story of both organs that V3 later scaled up.
MLA, up close
Shrinking the cache 57× without making heads share — the paper's real invention
Step 4 · Prior art
The old fixes shrink the cache by making heads share — and quality pays for it.
Step 3 put the serving bill on attention's desk. Attention already had two well-known diets before this paper — worth one step, because MLA is built to escape their trade-off.
The cache is huge because every head keeps its own keys and values. So the obvious surgery is sharing. Grouped-Query Attention (GQA) makes groups of heads share one key/value pair — 8 groups instead of 128 heads cuts the cache 16×. Multi-Query Attention (MQA) pushes to the limit: all 128 heads share a single key/value pair, a 128× cut. LLaMA-class models shipped with GQA; it works.
But heads are the whole point of multi-head attention — each one watches the sentence differently, and sharing K/V forces them to watch through the same pair of glasses. The paper measures the damage directly, training three otherwise-identical 7B models:
| 7B dense model | MMLU | BBH | Cache cut |
|---|---|---|---|
| with MQA | 37.9 | 33.2 | 128× |
| with GQA (8 groups) | 41.2 | 35.6 | 16× |
| with full MHA | 45.2 | 37.0 | 1× (none) |
Seven MMLU points between MQA and MHA — that's not a rounding error, that's a smaller model wearing a bigger model's name. So the question DeepSeek-V2 actually asks is sharper than “how do we shrink the cache?” It is: can the cache shrink like MQA while every head keeps its own view, like MHA? The fourth panel below is the answer, and the rest of Part B earns it.
Ablation from Appendix D.1 (Table 8), 7B dense models trained on the same 1.33T tokens, parameter counts matched by adjusting depth. BBH is the BIG-Bench Hard reasoning suite.
Step 5 · The compression
Don't cache the wardrobe — cache the packing list.
GQA and MQA cut the bag by deleting heads' individual keys and values, and Step 4's table showed the seven-point bill for doing so. MLA wants the small bag and the 128 distinct views.
Here's the observation that makes it possible. A token's 128 keys and 128 values are not 256 independent facts — every one of them is computed, by fixed weight matrices, from the same hidden vector h. They are 32,768 numbers of outfit generated from 5,120 numbers of person. The wardrobe is hugely redundant, and low-rank compression is the standard tool for redundancy: pass h through a skinny down-projection and keep only that.
Concretely — and this is the paper's equation 9 — the token's hidden vector is squeezed to a latent (a compact learned summary): c = WDKV h, taking 5,120 numbers down to 512. Two up-projection matrices, WUK and WUV, can regenerate all 128 heads' keys and values from c whenever they're wanted. So the cache keeps the 512-number note and throws the 32,768-number wardrobe away.
Watch our running example go through it: the token “liability”, sitting at position 91,204 of the report, arrives at some layer as a 5,120-number vector — the long bar at the bottom of the figure. One matrix multiply later it is the short violet note, and only the note enters the dashed bag. The amber and coral rows above it are never stored.
Two honest debts before moving on. First: why should 512 numbers preserve enough of 32,768 to keep quality? The intuition is the redundancy above, but intuition isn't evidence — Step 8 pays this off with the paper's ablation, which is stranger than “quality survives.” Second, and more urgent: regenerating keys and values “whenever they're wanted” should worry you. The model wants them at every generation step, for every past token. Didn't we just trade a memory disaster for a compute disaster?
Simplification ledger: V2 also low-rank-compresses queries (to 1,536 dims) — that saves activation memory during training but changes nothing in the cache, so this page leaves it folded (§2.1.2). Likewise the extra RMS Norm applied to each latent for training stability (§3.1.2). And the 512 is a design choice, not magic: it's 4 head-widths, chosen small enough to matter and large enough to hold 128 heads' worth of distinctions — Step 8's slider lets you feel that trade-off.
Step 6 · The absorption trick
Move the parentheses and the keys never need to exist.
Step 5 shrank the bag to a 512-number note per token — at the apparent price of re-inflating notes into keys and values for every past token, at every one of the thousands of steps it takes to write an answer. That price would sink the whole idea.
It never gets paid, and the reason is one line of linear algebra. An attention score is a dot product, q·k. Write both sides out: the query is q = WQh (from the current token, the one being generated), and the key would be k = WUKc (regenerated from a past token's cached note). Chain them:
WQ⊤WUK is a product of two fixed weight matrices — multiply them once, offline, call the result M. The score is just h⊤Mc.
Matrix multiplication is associative: it doesn't care where the parentheses sit. Grouped the left way, you rebuild k for every past token — the compute disaster. Grouped the right way, the two weight matrices merge into one matrix M before serving even starts, and at run time the current token's h is compared directly against the cached notes. The keys are never materialized. Neither are the values — the same move folds WUV into the output matrix WO. The paper calls this absorbing one matrix into another.
If that felt too cheap to be legal, you're in good company — we had to write it out with actual numbers before we stopped distrusting it. So let's do exactly that, with 2-dimensional toys. Take WQ = [[2,0],[1,1]], WUK = [[1,2],[0,1]], a current token h = (1, 2) and a cached note c = (3, 1). The slow path: q = (2, 3), k = (5, 1), score = 2·5 + 3·1 = 13. The absorbed path: M = WQ⊤WUK = [[2,5],[0,1]] (computed once), then Mc = (11, 1) and h·Mc = 1·11 + 2·1 = 13. Same score, and the second path never touched k. Now break it yourself:
Drag any slider — the two paths compute the score independently, and they cannot disagree
Slow path rebuild the key, then compare
Absorbed path M merged offline — k never built
scores agree: 13 = 13
What to look for: the left card does attention the textbook way; the right card only ever sees the cached violet note. Every slider position gives identical scores — associativity is doing all the work MLA needs.
After absorption, inference-time MLA looks like MQA — one shared cached object per token — but each head owns its own merged matrix Mi, so all 128 heads still read the note differently. MQA's cache bill, MHA's expressiveness.
Step 7 · The snag
RoPE jams the absorption — so position gets its own skinny channel.
The absorption in Step 6 worked because nothing stood between WQ⊤ and WUK — two constants, merged once. Position information is precisely the thing that has to stand between them.
Attention as computed so far is order-blind: “liability appears at position 91,204” is information no dot product has seen. DeepSeek models encode order with RoPE — rotary position embedding, which rotates each query and key by an angle proportional to its position, so that a score depends on how far apart two tokens are. Fair warning before the next paragraph: §2.1.3 is the densest spot in this paper, and we went around it three times before the shape of the problem clicked. Here is the slow version.
With RoPE, the score between our current token t and the cached “liability” at position j becomes q⊤ Rj−t k — a rotation matrix wedged between the query side and the key side, parameterized by the distance j−t. Now try to absorb: the merged matrix would be WQ⊤ Rj−t WUK. But t is the token being generated — it changes at every single step, so the distance changes, so the rotation changes, so there is no fixed M to precompute. Matrix multiplication is associative, not commutative: you can't slide the rotation out of the way. The escape routes are all bad — rebuild every past key each step (the compute disaster returns), or cache the rotated keys (the 32,768-number wardrobe returns).
The paper's exit is almost rude in its simplicity: if position jams the compressed channel, stop sending position through it. Split the job in two:
The content channel — everything from Steps 5 and 6, RoPE-free, absorbable, 128 dims per head served from the cached violet note. The position channel — a small side-car that carries RoPE and nothing else: each head gets a 64-dim decoupled query qR, and the token contributes one 64-dim rotated key kR shared by all 128 heads. Per head, the two channels just add up inside the softmax:
content dot + position dot, scaled by the joint width √192 — the paper's equation 18.
Why is this cheap? Sharing one rotated key across all heads is an MQA move — but applied only to position, the one signal where Step 4's quality tax has nothing to bite on (a rotation angle is the same fact for every head). The bag gains a single 64-number green strip per token per layer. In the figure, follow the two channels bottom to top: the violet note and the green strip are the only things inside the dashed bag.
Full formulas, including the query-side compression we folded away, are Appendix C of the paper (equations 37–47). File the green strip away for Step 11 — when V2 stretches its context from 4K to 128K, the adjustment (YaRN) is applied exactly there, because that strip is the only place position lives.
Step 8 · The receipt
576 numbers a token — and the ablation says quality went up, not down.
Content rides the cached note (Steps 5–6); position rides a shared 64-number strip (Step 7). Time to re-total the bill from Step 2 and audit the paper's headline numbers.
Per token, per layer, the bag now holds 512 + 64 = 576 numbers. Run the same arithmetic you ran in Step 2:
Against the 1,966,080 numbers of Step 2 that is a factor of 56.9 — call it 57×. Our 128K report drops from ≈ 515 GB of cache to ≈ 9.1 GB: from “six GPUs' entire memory for one user” to “a corner of one GPU.” Here is where that lands in the paper's comparison table, with V2's shapes plugged in:
| Mechanism | Cache per token (formula) | With V2's shapes | Quality |
|---|---|---|---|
| MHA | 2 · nh · dh · ℓ | 1,966,080 | strong |
| GQA (8 groups) | 2 · 8 · dh · ℓ | 122,880 | taxed |
| MQA | 2 · dh · ℓ | 15,360 | heavily taxed |
| MLA | (dc + dhR) · ℓ | 34,560 | stronger than MHA |
The paper's own summary of that last column: MLA costs the same as GQA would with just 2.25 groups — deep in quality-tax territory for actual GQA — yet outperforms full MHA. That is the IOU from Step 5, and the receipt is Appendix D.2: two MoE models, ~250B parameters, identical except for the attention mechanism, trained on the same 420B tokens:
| ~250B MoE, same data | Cache/token | MMLU | BBH | C-Eval |
|---|---|---|---|---|
| with MHA | 860.2K elem | 57.5 | 46.6 | 57.9 |
| with MLA | 34.6K elem (4%) | 59.0 | 50.7 | 59.2 |
A 25× smaller cache and higher scores across the board. Why compression would ever help quality, the paper doesn't really explain — low-rank bottlenecks can act as a regularizer, but treat that as our speculation, not the paper's claim. What the paper does own is the measurement.
One audit remains: the abstract says 93.3%, but 34,560 ÷ 1,966,080 says 98.2%. Different comparison. The 93.3% is measured against DeepSeek 67B as actually served — a 95-layer GQA model caching about 195K numbers ≈ 389 KB per token — while deployed V2 also squeezes each cached number to ~6 bits, landing near 26 KB per token. 26 ÷ 389 ≈ 6.7%, hence “reduced by 93.3%.” Same-architecture, same-precision, the honest number is the 57× you computed yourself. Now stress-test it:
Drag the context — then drag d_c and watch MLA's bar trade memory for capacity
bars drawn to the same scale — MHA is always the full track
At dc = 512: 576 numbers × 60 layers = 34,560 per token = 69.1 KB → 9.1 GB for the 128K report · 57× below MHA's 515.4 GB, which is ≈ 6.4 H800s' worth of memory (80 GB each) for a single conversation.
What to look for: at V2's shipped dc = 512, MLA sits between MQA and GQA on cost with none of their sharing. Push dc to 2048 and the discount fades; pull it to 64 and you'd be asking 128 heads to share a note thinner than one head's key. GQA-8 and MQA carry Step 4's quality tax; MLA's bar carries Table 9's quality bonus.
The 5.76× throughput headline follows from this step plus batch arithmetic: smaller cache → more concurrent users per node → >50K generated tokens/sec on one 8×H800 node (§3.2.3). DeepSeek 67B's per-token cache is reconstructed from its published config (GQA, 8 KV heads, 95 layers, d_h = 128); it matches the ≈400 KB/token bar in the paper's Figure 1(b).
The other economy: DeepSeekMoE
How 236B parameters charge like 21B — at a brisker pace
Step 9 · Fine-grained experts
Many small specialists plus a few generalists beat a handful of giants.
MLA settled the serving bill. The other headline — training 42.5% cheaper — comes from the block's other organ, the FFN, which is where nearly all of V2's 236B parameters actually live.
A Mixture-of-Experts (MoE) layer replaces the one big FFN with many smaller FFNs — experts — plus a router that sends each token to a few of them. Parameters stored: all of them. Parameters computed per token: only the chosen few. That's the whole decoupling.
DeepSeekMoE (adopted from the lab's earlier MoE paper) sharpens the recipe in two ways, both visible in the figure. First, fine-grained experts: instead of a handful of giants, each layer has 160 small experts (hidden width just 1,536) and the router picks 6. Picking 6 of 160 gives combinatorially more distinct teams than picking 2 of 8 — sharper specialization from the same parameter budget. Second, 2 shared experts that every token visits unconditionally, so grammar-level common knowledge settles there once instead of being copied into all 160 specialists. When “liability” from our report reaches this layer, the router scores all 160 (a softmax over dot products with each expert's learned centroid), and the output is: input + the 2 shared + the 6 winners, gate-weighted.
Where do “236B stored, 21B active” come from? Back-of-envelope, with rounding: each expert is 3 matrices of 5,120 × 1,536 ≈ 23.6M parameters; kept across 59 MoE layers, one expert-slot ≈ 1.4B. Then 162 experts ≈ 226B stored, plus ≈ 9B of attention machinery and ≈ 1B of embeddings → ≈ 236B. Active per token: 6 routed ≈ 8.4B + 2 shared ≈ 2.8B + the same 9B + 1B → ≈ 21B. The knob that sets the price is K, the number of routed experts per token:
Drag K — the compute bill moves, the 236B stored does not
K = 6 → ≈ 21.0B activated per token — the configuration V2 ships. The other 215B sleep until the router calls them.
What to look for: doubling K to 12 buys a bigger working team but nearly doubles the per-token bill; dropping to K = 1 collapses the combinatorics that make fine-grained experts worth having. All figures back-of-envelope from the shapes in §3.1.2.
Contrast worth filing: V2 keeps this MoE honest with auxiliary losses (next step). Its successor V3 drops those losses for a bias-nudge scheme — that story is the main lesson of our DeepSeek-V3 page, which assumes the MLA you just learned here.
Step 10 · Load balance
160 specialists are only cheap if the router actually uses them.
Step 9 handed the router 160 choices per layer. Routers left to themselves develop favorites — and a favorite expert is a failure mode with a name.
Routing collapse: early in training a few experts get slightly better, so the router sends them more tokens, so they get better still, until most experts sit untrained and the “160 specialists” are really five. Sparse compute also has a plumbing problem — experts live spread across 8 GPUs, and a token whose 6 experts sit on 6 different devices pays 6 network hops.
V2's countermeasures, at a brisk walk. Three auxiliary losses added to training: one nudging tokens to spread across experts (weight 0.003), one across devices (0.05), one balancing communication traffic (0.02). Device-limited routing: each token's experts may span at most M = 3 devices — the paper finds M ≥ 3 matches unrestricted routing. And a token-dropping escape valve: when a device still overflows its compute budget, the lowest-affinity tokens are skipped that layer (about 10% of training sequences are exempted so the model also learns the no-drop regime).
Every one of these balance losses is a small tax — gradient spent on logistics instead of language. V2 accepts the tax; a year later V3's aux-loss-free balancing showed how to stop paying it. We fold the three loss formulas here (equations 23–31 in §2.2.3 if you want them); nothing downstream depends on their exact form.
The receipts
Quality, cost, context — and what you should be able to rebuild
Step 11 · Report card
Top-tier scores while activating a third as much as its rivals.
Both organs are priced: attention remembers in 576-number notes, the FFN wakes 21B of 236B. The remaining question is whether the discounted model is actually good.
On MMLU it lands within half a point of LLaMA 3 70B while activating less than a third of the parameters per token — the bars below keep each model's activated count next to its score. Two honest asterisks before you read them. LLaMA 3 saw over four times V2's English data, and on English commonsense and trivia it still wins; V2's edge is the bilingual trade — on Chinese benchmarks it and Qwen1.5 trade blows at the top of the open field. And every economics headline on this page is measured against DeepSeek's own dense 67B, not some universal baseline.
MMLU, 5-shot · open-source models, May 2024 · axis starts at 60
The long-context claim closes a loop from Step 7: because position lives only in the decoupled RoPE strip, stretching the context from 4K to 128K meant adjusting that one channel (with YaRN) and training a further 1,000 steps at 32K — the compressed content channel never had to know. Alignment gets one sentence and a pointer: the base model was instruction-tuned on 1.5M examples, then aligned with GRPO — the critic-free RL method DeepSeek later made famous — and that story is told properly on our DeepSeek-R1 page.
“Even with only 21B activated parameters, DeepSeek-V2 and its chat versions still achieve top-tier performance among open-source models.” — the abstract, arXiv 2405.04434
Step 12 · Self-check
The whole argument, compressed to six questions.
One report, two surgeries, one receipt. Before you close the tab, try to rebuild each piece from memory — peek only after you've committed to an answer.
Why does long-context generation hit a memory wall rather than a compute wall?
Every token already read must keep its keys and values available — the KV cache — and that store grows with context × layers × heads × head-width. It occupies GPU memory for the whole conversation and caps the batch size, which caps throughput.
What exactly does MLA cache for one token, in one layer?
576 numbers: a 512-dim latent note (the joint compression of all 128 heads' keys and values) plus a 64-dim shared RoPE key. Standard MHA at the same shapes would cache 32,768 — a 57× difference.
Why doesn't regenerating keys from the note cost extra compute at inference?
It never happens. By associativity, q·k = h⊤(WQ⊤WUK)c, and the middle product is merged into one matrix offline. Scores are computed directly against cached notes; WUV is likewise absorbed into the output projection.
Why does RoPE break that absorption, and what is the fix?
RoPE inserts a rotation between the two matrices whose angle depends on the current generation step, so no fixed merged matrix exists. Fix: keep the compressed channel position-free, and carry position in a separate 64-dim RoPE'd channel — per-head queries plus one key shared by all heads.
What makes DeepSeekMoE different from a classic few-big-experts MoE?
Granularity and sharing: 160 small routed experts with 6 chosen per token (combinatorially more specialist teams), plus 2 shared experts that always run so common knowledge isn't duplicated. Balance comes from three auxiliary losses, device-limited routing (M = 3), and token-dropping.
Where do 42.5%, 93.3% and 5.76× each come from?
All vs DeepSeek 67B: GPU-hours per trillion training tokens (300.6K → 172.8K = −42.5%); served KV cache per token including 6-bit quantization (≈389 KB → ≈26 KB = −93.3%); and peak generation throughput on the same node (5.76×).
Homework — (1) Reproduce the 57× on paper: 2·128·128·60 against (512+64)·60. (2) Price a 1M-token context under MLA at BF16 — about 72 GB — and notice it barely fits one GPU; that's why the cache diet didn't end with this paper. (3) Explain to a colleague why sharing keys across heads taxes quality in GQA but sharing the 64-dim RoPE key in MLA doesn't.
The blueprint that V3 and R1 scaled — and the cache diet everyone copied.
DeepSeek-V2 is the paper where “open-source model” started to mean “cheap to serve,” not just “free to download.” Its two organs became the standing architecture of everything the lab built next.
DeepSeek-V3
The same two organs, scaled to 671B stored / 37B active. MLA carries over almost unchanged; the balance losses of Step 10 retire in favor of a per-expert bias nudge — the headline lesson of our V3 page.
DeepSeek-R1
The reasoning model built on V3's base — which is to say, on V2's skeleton. GRPO, used quietly here to align V2 Chat, moved to center stage as R1's training engine.
MLA leaves home
Latent-compressed KV became a standard serving option: open inference stacks grew dedicated MLA paths, and follow-up work retrofits existing GQA models into MLA form to inherit the smaller cache.
A year after release, the interesting question had inverted: not “can compressed attention match full attention?” but “why would you still pay for the uncompressed kind?”