Serving Engines and PagedAttention

You don't assemble the KV cache, continuous batching, quantization, and speculative decoding by hand — you use a serving engine that has already solved the hard parts. And the idea that ties them together, PagedAttention, is a borrowed operating-systems trick: manage the KV cache like virtual memory, in pages, and the waste that throttled everything disappears.

The previous posts covered the individual optimizations. In practice you get them through an inference serving engine — vLLM, TGI, TensorRT-LLM, and others — purpose-built systems that turn a model file into a high-throughput, production-grade API. This post explains what a serving engine does, and dwells on PagedAttention, the memory-management idea that made modern high-throughput serving possible and that unifies the KV cache and batching stories.

What a serving engine does

Naively, you could load a model with a basic library and call it in a loop — and get terrible throughput, because you’d be missing every optimization in this series. A serving engine is the layer that implements them together and exposes a clean API. Its responsibilities:

The point of a serving engine is that all of this is hard and coupled — continuous batching needs dynamic KV cache allocation, which needs PagedAttention, which needs custom kernels — and the engine solves it as an integrated whole so you don’t have to.

PagedAttention: the key idea

The KV cache post described the waste problem: because a request’s final length is unknown, naive systems pre-allocate one contiguous block per request for the maximum length, and the resulting internal/external fragmentation wastes most of the KV cache memory — capping batch size and throughput. PagedAttention, introduced with vLLM, solves this by borrowing the oldest trick in operating systems: virtual memory and paging.

The idea: instead of one contiguous block per request, divide the KV cache into small, fixed-size blocks (pages), and allocate them to a request on demand, one block at a time as its sequence grows. A request’s tokens no longer need to live in contiguous memory — a lookup table (like an OS page table) maps the request’s logical token positions to wherever the physical blocks actually are.

Naive (contiguous, per request):
  [■■■□□□□□□□□□□□□□]  reserved for max length; most unused → wasted

PagedAttention (paged, on demand):
  Req A tokens → [blk 7][blk 2][blk 9]      allocated as it grows
  Req B tokens → [blk 3][blk 5]             no over-reservation
  free blocks reused instantly by any request

The consequences map directly onto the problems earlier posts raised:

Prefix sharing: paging’s bonus

Paging unlocks a second win that’s hard to get with contiguous allocation: sharing KV cache blocks across requests. Because the cache is in blocks with a mapping layer (like an OS sharing memory pages between processes), two requests with a common prefix — say, the same long system prompt, or the same document — can share the physical blocks for that shared prefix instead of each storing its own copy.

This is a large practical win for common serving patterns:

This is why prefix caching is such an effective optimization, and it falls out naturally from managing the KV cache as shareable pages — copy-on-write semantics (from OS virtual memory) let shared blocks diverge only when a request actually writes different tokens.

The engine landscape

You don’t need to memorize products, but knowing the shape of the field helps you choose:

The choice among self-hosted engines usually comes down to ecosystem fit, hardware, and how much performance you need versus operational simplicity — but they all share the same core: PagedAttention-style KV management plus continuous batching plus optimized kernels.

Using a serving engine well

Serving engines are where all the theory becomes a running system. What remains is operating that system at scale — spreading it across GPUs — and tuning it against latency, throughput, and cost targets, the final two posts.

Key takeaways

Further reading

Sources & References

Serving engine features