AI Infra Interviews logo
LLM Inference & Serving / 03
easy★ EssentialNewBasetenTogether AIAnyscale

What is the difference between static and continuous batching, and why did it change LLM serving?

A batch of eight requests finishes when the longest one does, and seven slots compute padding until then. The fix is to make the scheduling unit one decode step, and the throughput math shows why that was worth several times the hardware.

Updated Sep 2026 · Grounded in real AI infrastructure interview loops and written to a senior-engineer editorial bar, with every number worked and every diagram hand-built.

TL;DR: Static batching groups requests at arrival and runs the group until its longest member stops, so slots go idle as short answers finish. Continuous batching re-forms the batch at every decode step: finished sequences leave, queued ones join, and the GPU runs one pass over whatever is active. Because each decode step reads all 141 GB of a 70B model's weights whether one or sixty-four sequences ride along, keeping the batch full raises throughput several times over while per-token latency moves by a millisecond or two.

How to approach it

Frame the problem first: LLM requests have wildly different output lengths, and a batch is only as short as its longest member. Ask about the engine and traffic shape (chat with variable outputs versus fixed-length classification), because static batching is fine for the latter. Then say you will show the cost of an idle slot with the decode bandwidth arithmetic, describe the per-step scheduler loop, and finish with the two things it introduces that the interviewer will ask about next: prefill interference and KV admission.

A strong answer

A typical situation: a serving deployment reports high GPU utilization and low throughput, and the two are both true. Seven of its eight batch slots are computing padding while the longest request finishes.

Picture 8 requests arriving together for Llama 3.1 70B on 4 H100s with tensor parallelism. One answers in 12 tokens, another in 900. Under static batching all 8 run for 900 steps. After step 12 one slot is padding, after step 100 half of them are, and the queue behind them waits the full 900 steps for a slot. The GPU reports high utilization the entire time because it is running the same kernels on padded rows.

CONTINUOUS BATCHING (run, then toggle)
Each column is a time step, each row a GPU slot. Static batching waits for the whole batch to finish, so short requests leave idle gaps (red) until the longest one is done. Continuous batching refills a slot the instant it frees up, keeping the GPU full. Utilization: 60%.

Why the idle slot is expensive comes from the decode step cost:

inputs: Llama 3.1 70B bf16 on 4 × H100 SXM
  W = 141.2 GB, aggregate HBM = 4 × 3.35 = 13.4 TB/s
  KV per sequence at 2k context = 328 KB × 2,048 ≈ 0.67 GB

step time ≈ (W + B × KV) ÷ bandwidth
  B = 1:   141.2 ÷ 13.4 ≈ 10.5 ms   → 95 tokens/s
  B = 4:   (141.2 + 2.7) ÷ 13.4 ≈ 10.7 ms   → 373 tokens/s
  B = 32:  (141.2 + 21.5) ÷ 13.4 ≈ 12.1 ms  → 2,640 tokens/s
sanity: 32x the sequences cost 15% more per step, because the weight read dominates
        and it is paid once per step regardless of batch

A static batch of 8 averages 3 to 4 live sequences over its lifetime, so it sits near the 373 tokens/s row. Continuous Batching keeps the running set near its cap whenever demand exists, so the same hardware sits near the 2,640 row. That gap, roughly 7x on this traffic, is the reason vLLM and TensorRT-LLM's in-flight batching displaced request-level batching.

The scheduler loop is simple to state. After every forward pass: free the KV blocks of sequences that emitted a stop token or hit max length; admit waiting requests while free blocks cover their prompt plus room to grow; run the next step over the new set. Admission is gated on memory, never on a slot count, which is where the KV cache enters. A cap of 128 sequences that the KV pool cannot honor at typical context produces preemption storms under load: the engine evicts a running sequence, swaps or drops its blocks, and recomputes later. A non-zero preemption counter is the signal that the ceiling is memory rather than scheduling.

The cost is prefill interference. A newly admitted request needs its prompt processed, and the naive policy runs that prefill as its own step. A 20k-token prompt then stalls every running stream for the length of that prefill (about 900 ms on this fleet at 40% MFU), and the inter-token latency histogram grows a second mode aligned with admissions. Chunked Prefill is the remedy: slice the prompt into a per-step token budget and mix it with decode.

The decision: use continuous batching for anything with variable output length, which is every chat and agent workload. The signal that the fix landed is a p99 inter-token latency that stops tracking the longest request in the batch. The reversal condition: fixed-length, offline scoring where every input costs the same, where static batching with packed inputs is simpler and equally fast.

What interviewers probe next

  • "A request arrives while a batch is mid-decode. What happens?" It is admitted on the next step if KV blocks are free, its prompt is prefilled (in one step or in chunks), and it decodes alongside the others from then on; nothing waits for the batch to finish.
  • "Does continuous batching change per-token latency?" Slightly upward, from 10.5 to 12 ms in the example, because each step now reads more KV; the throughput gain is what the extra millisecond buys.
  • "Which metrics tell you it is working?" Running and waiting request counts, KV utilization percent, preemptions per second, and the inter-token latency histogram; a bimodal ITL says prefill is interfering.

Common mistakes

  • Explaining the gain as "better GPU utilization" without the weight-read argument, which is the mechanism.
  • Confusing it with Triton Inference Server's dynamic batching, which groups at arrival and still runs each group to completion.
  • Setting the sequence cap by GPU count rather than by KV budget ÷ expected context.
  • Not knowing that admission triggers prefill and therefore an ITL spike.

Key takeaways

  • Unit of scheduling is one decode step; sequences leave when they finish and new ones join on the next step.
  • A 70B decode step on 4 H100s costs about 10.5 ms at batch 1 and 12 ms at batch 32; the weight read is paid once per step.
  • Admission is gated on free KV blocks; preemptions mean the KV pool, not compute, is the ceiling.
  • Prefill of admitted requests is the main ITL spike; chunked prefill fixes it.
That one was free — and so are 10 answers per topic without an account. Signing in doubles that to 20, opens the Plus lessons in the courses, and remembers which topics you keep getting wrong.no card · Google sign-in · nothing to cancel
HOW DID IT GO?
0
READING SIGNED OUT

Signing in doubles your free answers, from 10 to 20 per topic, and the site starts remembering you: mastery per topic, bookmarks, and a next-focus recommendation. Free, no card.

Sign in free

The concepts behind this question

Ranked by how closely each one overlaps this question's topic, so the first card is the thing to read if the answer above moved too fast.

Core
🚀 Inference & ServingSign in
Continuous BatchingContinuous batching schedules at the granularity of a single decode step instead of a whole request, so a finished sequence's slot is refilled on the next iteration rather than when the longest request in the batch ends. It is the scheduling idea that turned LLM serving from a padded, half-idle GPU into one that stays full, and it decides how the engine's scheduler, memory manager and latency SLOs interact.
Advanced
🚀 Inference & Serving🔒 Premium
Chunked PrefillA long prompt's prefill can occupy a GPU for hundreds of milliseconds, and every sequence mid-decode on that GPU waits for it. Chunked prefill splits the prompt into fixed token budgets and interleaves each chunk with a decode step, so decode latency stays flat at the cost of a slower first token for the long prompt. The chunk budget is a knob between TTFT and TPOT, and the interview question is how you would set it.
Core
📐 AI Systems DesignSign in
Designing for Latency SLOsA latency objective is met or missed by the sum of a chain of delays, and the way to design for it is to write the chain down with a number on every link, find the links that dominate at the tail, and attack those. For an LLM request the chain is network, gateway, router, queue, prefill, then the decode loop, and the tail is shaped by queueing and by the size of the batch the request lands in. This page decomposes a 500 ms time-to-first-token budget link by link, derives how queueing turns a comfortable median into a broken p99, and gives the design moves (admission control, chunked prefill, priority lanes, hedging) that hold it.
Advanced
🚀 Inference & Serving🔒 Premium
PagedAttentionPagedAttention stores the KV cache in fixed-size blocks scattered across HBM and maps each sequence's logical positions to physical blocks through a block table, the same trick an operating system uses for virtual memory. It removes the reservation and fragmentation waste of contiguous allocation, lets blocks be shared between sequences, and is why an engine can decide admission by counting free blocks.
UP NEXT ON YOUR JOURNEY
FEDITOR'S NOTE

Scored on the mechanism (why the weight read amortizes) and on knowing what the scheduler does when a request arrives mid-batch.

DISCUSSION · 0

No comments yet — be the first to share your approach.