Skip to content
Tech News
← Back to articles

LRU is harder to beat than the KV-cache papers suggest

read original get Designing Data-Intensive Applications by Martin Kleppmann → more articles
Why This Matters

A developer built a block-granular prefix-cache simulator and replayed 68k real Claude Code requests plus 23k Mooncake requests, failing to beat production LRU with three alternative eviction policies. It's a useful empirical check on a fast-growing body of papers claiming LRU is wrong for agentic LLM serving, and it suggests the dominant source of recomputation is tight tool-calling loops rather than idle sessions.

Key Takeaways
Worth a Look

Designing Data-Intensive Applications by Martin Kleppmann — If benchmarking cache eviction policies against real request traces sounds like your idea of fun, Kleppmann's classic is the definitive deep dive into caching, storage engines, and the tradeoffs behind systems like this. It's the book that turns intuitions about LRU and workload behavior into rigorous mental models.

See Designing Data-Intensive Applications by Martin Kleppmann on Amazon → Affiliate link — we may earn a commission on purchases, at no extra cost to you. Product picked by AI based on this article; it is not a tested recommendation.

LRU is harder to beat than the KV-cache papers suggest

I replayed 68,266 requests from 393 real Claude Code sessions and 23,608 Mooncake requests through a prefix-cache simulator, tried to beat the production baseline three different ways, and failed. The interesting part is why: under capacity pressure, most recomputation comes from tool-calling loops seconds apart, not from sessions idling past a TTL — and the TTL never fires at all.

Everything here reproduces from a cold checkout with make setup data repro .

Contents

Cross-request KV prefix caching is the largest practical lever in agentic LLM serving. It's why your coding agent's fiftieth turn costs a fraction of its first. Every serving stack has one — vLLM's automatic prefix caching, SGLang's RadixAttention, LMCache, Mooncake Store — and all of them evict with LRU by default. (SGLang also ships LFU, SLRU, Priority and others behind --radix-eviction-policy ; LRU is the shipped default.)

There's a large, fast-growing literature arguing LRU is the wrong policy for agentic workloads, because agent sessions go idle and LRU can't tell a paused session from a dead one. The argument is intuitive. I believed it, and built a simulator to exploit it.

It didn't work, and why it didn't work turned out to be more interesting than the policy would have been.

What I built

A block-granular, discrete-event simulator of a cross-request prefix cache. Three properties that matter, and that quick implementations tend to get wrong:

Hits are prefix-contiguous. A hit is the longest resident prefix of the block chain, not a set intersection. Miss one block at depth 3 and everything after it is unusable even if it's still resident.

... continue reading