Inference serving and batching
Reason about prefill, decoding, KV-cache memory, admission control, and latency when serving language models.
On this page
The question for today
What you’ll understand
- Distinguish time to first token from time between output tokens.
- Estimate KV-cache demand from model and request dimensions.
- Choose batching and admission policies that respect latency constraints.
A language-model endpoint is a stateful queue wrapped around repeated numerical computation. Two requests with identical input size can occupy the system for different durations because their outputs differ. A serving design must budget prompt processing, token generation, memory growth, cancellation, and overload. Requests per second alone hides these distinctions; specify the prompt and output workload before comparing two deployments.
Separate prefill from decoding
Prefill processes the prompt and builds attention keys and values for its positions. Many prompt positions can be processed together. Autoregressive decoding then generates successive tokens, each depending on previous outputs. Reusing the key–value cache avoids recomputing prior keys and values, but the cache grows with retained context. Prefill often offers more parallel arithmetic, while decoding can be limited by memory traffic at modest batch sizes. The actual bottleneck depends on model architecture, kernels, and hardware.
Measure time to first token from the user's request, including queueing and prefill, and inter-token latency during generation. Also measure successful completed requests and useful output tokens per second. A high throughput result can coexist with frustrating pauses. Cancellation should release cache blocks and stop work promptly. Streaming a first token quickly while the remaining response stalls is not equivalent to meeting an end-to-end service objective; record both phases and the distribution of request lengths.
Count the cache rather than just the weights
For a conventional decoder cache, each retained token stores one key and one value for every attention layer and key–value head. Multiply layer count, KV-head count, head dimension, element bytes, and retained tokens, then include both keys and values. Grouped-query attention can have fewer KV heads than query heads; using the query-head count in that case overestimates the cache. Tensor-parallel placement, quantization metadata, and implementation details can change per-device accounting.
Weights, cache, activations, temporary workspaces, and allocator fragmentation share device memory. Admission control therefore needs a token budget, not just a request-count cap. Reserve room for possible generation or explicitly support preemption and recomputation. PagedAttention demonstrates block-based cache allocation that reduces allocation waste and supports sharing. It does not make context memory free, and a serving system still needs rules for which requests to admit, suspend, or reject.
Batch for useful work without starving small requests
Static batching waits for a group and often lets the longest request determine the group's completion. Continuous batching can admit and retire requests between decoding iterations. Larger active batches amortize weight reads, but also increase cache occupancy and can lengthen token latency. Long prefills can delay active decodes unless the scheduler interleaves or chunks work. A maximum batch size is therefore only one part of scheduling; token budgets and phase-aware fairness matter.
Benchmark a workload distribution, including long prompts, long generations, cache misses, cancellations, and bursts. Set a queue deadline and reject work that cannot meet its deadline instead of building an unbounded queue. Consider fairness between users and between interactive and offline traffic. Repeatedly inspect quality if precision or cache policies change. Serving optimization must preserve the intended model behavior and account for completed useful work; repeated retries and abandoned responses can inflate apparent token throughput.
Work it through
Fit a batch within a cache budget
A fictional decoder has 32 layers, eight KV heads, 128 elements per head, and 2-byte cache elements. Each active request retains 4,096 tokens. There are 16 GiB available for the cache after other allocations.
Compute cache bytes per token: 2 × 32 × 8 × 128 × 2 = 131,072 bytes, or 128 KiB.
A 4,096-token request needs 131,072 × 4,096 = 536,870,912 bytes, or 0.5 GiB.
Divide the 16 GiB cache budget by 0.5 GiB/request to obtain an ideal bound of 32 such requests.
Reserve memory for growth and block slack. If policy limits cache use to 80% of the budget, floor(12.8/0.5) = 25 requests fit this conservative equal-length admission model.
The arithmetic ceiling is 32 requests; the stated 80% policy admits 25. Neither number establishes the latency-optimal batch size.
The living notebook
Explore the model
Interactive lab · queue
Explore admission pressure
Vary arrival λ and service μ in the fluid queue max(0, 4 + (λ − μ)t). Treat an item as fixed token work. The separate M/M/1 mean assumes Poisson arrivals and exponential single-server service. Variable prompts, prefill/decode scheduling, and cache allocation are outside both models.
- Fluid backlog
- 4
- Net rate · λ − μ
- −1 /s
- M/M/1 mean residence
- 1 s
Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forA finite service rate needs bounded admission; increasing backlog cannot increase token-processing capacity.
Pause & reason
Check your understanding
Your turn
Try it yourself
Using the worked model, estimate cache memory for 12 requests retaining 6,144 tokens each. With queueing of 0.2 s, prefill of 0.3 s, and 100 output tokens at a mean 0.025 s/token, estimate response time.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
A 6,144-token request is 1.5 times the worked request. Add queueing, prefill, and the generation phase; do not treat first-token latency as total latency.
Compare with the solution
Each request needs 0.75 GiB, so 12 need 9 GiB before allocation overhead. The response estimate is 0.2 + 0.3 + 100 × 0.025 = 3.0 seconds. Its approximate first-token waiting component is 0.5 seconds plus any first decode step, whereas the complete output takes much longer.
Keep the idea
Take it with you
- Prefill and decoding have different latency and resource behavior.
- KV-cache memory grows with retained tokens, not merely request count.
- Batching policy must balance throughput, fairness, memory, and deadlines.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.