Saoirse Mulligan 7 min readA language model API appears to process one request at a time: a prompt enters, tokens emerge, and the request ends. The server underneath sees something more difficult. Prompts have different lengths. Responses stop unpredictably. Some users expect an immediate first token; others submit long background jobs. Meanwhile, the accelerator performs best when given substantial, regular blocks of work.
Continuous batching is the scheduling technique that reconciles these incompatible shapes. Instead of waiting for a fixed group of requests to finish together, the server revises the batch as inference proceeds. Completed sequences leave; waiting sequences enter. This apparently modest change is one reason modern inference systems can serve interactive traffic efficiently.
The Problem Hidden by the API
Transformer inference has two operationally distinct stages. During prefill, the model processes the prompt and constructs the key-value cache, or KV cache, used by attention. During decode, it generates subsequent tokens, usually one token per active sequence per model step.
Prefill can expose substantial parallelism because many prompt tokens are processed together. Decode is iterative: every new token depends on the preceding state. A request asking for a brief classification may finish quickly, while another request in the same batch may continue generating a long report.
With static batching, the server assembles several requests, runs them as a group, and waits until the group completes before admitting replacements. Finished requests therefore leave empty positions behind. One unusually long generation can hold the batch open while accelerator capacity goes unused.
Continuous batching moves the scheduling boundary inside generation. After a decode step, the server can remove completed sequences and admit new work. The operative unit is no longer a fixed request cohort. It is a changing set of active sequences.
What Happens During a Scheduling Cycle
A serving engine typically maintains waiting, running, and sometimes paused queues. Exact implementations differ, but a cycle can be understood through five operations:
- Inspect: identify completed sequences, available cache capacity, and waiting requests.
- Evict or pause: remove finished work and, under pressure, suspend lower-priority sequences.
- Admit: select prompts or resumed sequences that fit the current token and memory budget.
- Execute: run a prefill chunk, a decode step, or a mixture supported by the engine.
- Update: append generated tokens, extend cache state, apply stopping rules, and reschedule.
Suppose requests A, B, and C are decoding together. At the next step, A emits an end marker, while B and C continue. The scheduler can place request D into A's vacated capacity. If D has a large prompt, however, admitting its entire prefill may delay the next token for B and C. The scheduler may instead process D's prompt in chunks between decode iterations.
This is the central mechanism: continuous batching converts serving into online resource allocation. The model weights remain unchanged. What changes is which tokens receive compute, when their cache pages occupy memory, and how long each request waits.
Why the KV Cache Governs Admission
Model weights occupy a largely fixed amount of device memory. The KV cache grows with active context: prompt tokens and generated tokens both consume it. Consequently, a server can have available arithmetic capacity yet be unable to admit another request because cache memory is constrained.
Naive systems reserve contiguous cache space according to a request's maximum possible sequence length. If the request stops early, much of that reservation is wasted. Modern engines often divide cache storage into blocks or pages. A sequence receives additional blocks as its context grows, producing an arrangement analogous to paged virtual memory.
| Mechanism | What it improves | What it introduces |
|---|---|---|
| Continuous admission | Reuses batch positions as sequences finish | More complex scheduling and fairness behavior |
| Paged KV cache | Reduces waste from oversized contiguous reservations | Block metadata and allocation overhead |
| Chunked prefill | Prevents long prompts from monopolizing a scheduling cycle | Additional coordination and possible prefill delay |
| Prefix sharing | Reuses cache state for identical prompt prefixes | Matching, lifetime, isolation, and invalidation concerns |
| Preemption | Allows urgent work to proceed under pressure | Recomputation or cache-transfer cost for paused requests |
Paging does not make memory unlimited. A long-context request still consumes cache across many layers, and growing generations can create pressure after admission. The scheduler must therefore budget not only for present occupancy but also for uncertain future growth.
Throughput and Latency Pull in Different Directions
A fuller batch generally uses accelerator resources more efficiently, but waiting to fill that batch delays requests. Continuous batching reduces the need for an explicit batching window, yet it does not eliminate the conflict.
Consider an interactive assistant sharing a server with document summarization jobs. Aggressively admitting large prefills may raise total token throughput while increasing the interval between output tokens for the assistant. Reserving frequent decode opportunities protects interactivity but can leave less room for efficient prefill work.
This creates several distinct service objectives:
- Time to first token: how long a request waits before output begins.
- Inter-token latency: how regularly tokens arrive after generation starts.
- End-to-end latency: how long the complete response takes.
- Throughput: how much aggregate token work the server completes.
- Fairness: whether large or low-priority requests can indefinitely delay others.
No scheduler optimizes all five without compromise. A product that streams prose values regular decode progress. A batch extraction system may tolerate waiting in exchange for higher aggregate throughput. The appropriate policy follows from the experience being promised, not from accelerator utilization alone.
A Worked Example: When One Long Prompt Arrives
Imagine a server decoding four chat responses. A fifth request arrives containing a long document and asks for a short answer. Its prompt requires significant prefill work, although its eventual generation may be brief.
One policy runs the complete prefill immediately. The newcomer receives a faster first token, but the four existing streams may visibly pause. Another policy postpones the newcomer until decode traffic subsides. Existing users remain smooth, but the document request waits without progress.
Chunked prefill offers a middle path. The scheduler processes part of the document, returns to a decode step for the active chats, then processes another prompt chunk. This limits blocking, but it also increases the document's total prefill duration and complicates the choice of chunk size.
The example reveals why request count is a poor measure of load. One short prompt requesting many output tokens, one enormous prompt requesting one token, and one cached prompt may each create a different blend of computation, memory occupancy, and scheduling duration. Token budgets and cache budgets provide a more faithful operational vocabulary.
Where Continuous Batching Stops Helping
Continuous batching cannot repair every inference bottleneck. If only one request is available, there may be nothing useful to batch. If memory bandwidth dominates decode, adding sequences eventually reaches a saturation point. If the KV cache is full, new work cannot enter merely because a logical batch position became free.
Workloads can also be structurally incompatible. Different models obviously cannot share the same forward pass. Requests using different adapters, constrained-decoding states, multimodal inputs, or specialized attention patterns may be batchable only with additional grouping logic—or not batchable at all in a given engine.
Preemption is similarly nonmagical. A paused sequence's state must remain in device memory, move elsewhere, or be recomputed later. Keeping it consumes scarce capacity; transferring it consumes bandwidth; recomputing it consumes time and compute. The best choice depends on sequence length, expected pause duration, and hardware topology.
Finally, scheduler efficiency cannot compensate for an unsuitable product contract. Unlimited output lengths, unbounded context, and identical priority for every request create pathological contention. Sensible limits are part of serving architecture, not merely commercial policy.
The Open Questions Are Product Questions
The next advances are likely to concern coordination across layers. A router may need to know not only which replica is alive, but its current cache pressure, prompt mix, adapter availability, and likely completion horizon. A scheduler may need to distinguish human-visible streams from asynchronous agent tasks rather than treating both as generic token requests.
Fairness remains especially unsettled. First-come, first-served is simple but allows large requests to impose broad delays. Shortest-job-first requires estimates of generation length that are inherently uncertain. Priority tiers protect important traffic but can starve background work unless aging or quotas are introduced.
There is also a deeper opportunity in exposing intent. If an application can declare a latency deadline, maximum output, interruptibility, and whether partial results retain value, the serving layer can make better decisions than it can from a prompt alone. Inference APIs may gradually evolve from specifying only model and tokens toward specifying service semantics.
Continuous batching is therefore more than a GPU optimization. It is the mechanism by which an inference platform decides whose computation advances at each moment. Once that is visible, latency ceases to look like a single performance number. It becomes the outcome of memory allocation, admission control, workload shape, and an explicit theory of priority.
This post was drafted with AI assistance and reviewed against our editorial policy before publication. Corrections are made at the source, on the page, with the date shown.
Rate this article
Discussion
Comments are moderated. Read our editorial policy.