Model Servingthe restaurant around the chef

Topic 37 of 90Module 4: Inference & Optimization4 min read

A model is a chef; a serving engine is the entire restaurant — host stand, order queue, table management, expo window. Running model.generate() in a Python loop is a chef cooking in an empty room. The serving layer is what the previous two topics require to exist: something has to schedule continuous batches, manage every diner's KV cache, stream results, and speak a standard API. Concepts today; hands-on tooling in Module 5.

The flagship idea: PagedAttention — vLLM's founding insight, and a beautiful case of stealing a 50-year-old OS trick. The problem: early engines pre-allocated each request's KV cache as one contiguous block sized for the maximum possible length — like reserving a 40-seat private room for every party because they might bring 40 people. Measured waste in pre-vLLM systems: 60–80% of KV memory held but unused. Since Topic 36 established that KV memory is the batch-size ceiling, most of the restaurant's capacity sat empty-but-reserved.

PagedAttention applies virtual memory: chop the cache into small fixed-size blocks ("pages," e.g. 16 tokens each), allocate them on demand as a sequence grows, let one request's pages scatter anywhere in VRAM, and keep a lookup table mapping logical position → physical page. Waste collapses to a few percent, effective batch size multiplies, throughput follows. Seat parties at whatever free tables exist, tracked by the host's chart — no more empty private rooms.

Paging enables a second, product-critical trick: prefix caching. If a thousand requests share the same 3,000-token system prompt (every agent product ever), compute its KV once and let all thousand requests point at the same physical pages — copy-on-write, exactly like OS memory sharing. Same for multi-turn chat: the conversation's cache survives between turns instead of being recomputed (there's Topic 5's "you re-pay for the whole whiteboard each turn" — softened, at the serving layer, and it's why providers now sell discounted "cached input tokens"). SGLang, vLLM's main rival, made radical prefix-sharing (RadixAttention) its whole founding thesis — for agent workloads with massively shared prompts, it's brutal.

The landscape, mapped once so Module 5 has pegs to hang on:

EngineOne-line identityReach for it when
vLLMOpen-source throughput standard; PagedAttention's homeDefault for GPU serving
SGLangPrefix-sharing specialist, very fastAgent/structured workloads, shared prompts
TensorRT-LLMNVIDIA's maximum-performance compiler; complexSqueezing the last 20% at scale
llama.cpp / OllamaCPU + Mac + consumer hardware; GGUFLocal, edge, your M4
TGIHugging Face's serverHF-ecosystem deployments

Everything above speaks the OpenAI-compatible API — the industry's lingua franca. Ship your app against that interface and the backend (local Ollama ↔ vLLM cluster ↔ commercial API) becomes a config change. This is the single highest-leverage architecture decision in AI product code.

The remaining ops vocabulary, one line each: streaming — tokens pushed as generated (SSE), non-negotiable for chat UX (formalized next topic); metrics — TTFT, inter-token latency, throughput, queue depth: the four dials of a serving dashboard; cold starts — loading tens of GB of weights takes tens of seconds to minutes, which makes naive request-based autoscaling miserable (hence keep-warm pools, and why "serverless GPU" is a hard product); multi-GPUtensor parallelism splits every layer across GPUs (needs NVLink-class interconnect; how 70B+ models get served at all) while pipeline parallelism assigns different layers to different GPUs (tolerates slow links, adds latency); and multi-LoRA servingTopic 22's wardrobe realized: engines hot-swap per-request adapters over one shared base, making per-customer fine-tunes economically absurd not to offer.

Summary

Serving engines wrap the model with scheduling, paged KV management, prefix caching, streaming, and standard APIs. PagedAttention (virtual memory for the cache) killed the 60–80% waste that capped batch sizes; prefix caching makes shared prompts nearly free; OpenAI-compatibility keeps your backend swappable.

Mental model

Chef vs restaurant. The same chef serves 10× more diners with a good host (scheduler), flexible seating chart (paged KV), a standing mise en place for the regulars' usual order (prefix cache), and dishes leaving as they're plated (streaming).

Mistakes to avoid

  • Hardcoding a vendor SDK deep into product code. Speak OpenAI-compatible at the boundary; the freedom to swap backends is worth more than any single backend.
  • Ignoring prefix caching when your product has a huge system prompt. That's paying full prefill price per request for tokens the engine would happily serve from cache — often the single largest instant cost/TTFT win available.

Exercise

Compute what PagedAttention saved. Old world: 24 GB GPU, 8B Q4 model (4.5 GB weights, 2 GB overhead), each request pre-reserves a full 8K-context cache at 128 KB/token = 1 GB — max concurrent requests? New world: requests actually average 1.5K tokens, paged allocation ≈ actual use — now how many fit? (≈17 vs ≈90.) That ratio, times every GPU in a fleet, is why one memory-allocation paper reshaped an industry.