Sign in to keep reading
“How LLM Inference Actually Works” is free with an account. Your progress and bookmarks follow you across devices.
Sign in to continueNEW: ML Mock & Coaching with a 20+ year experience coach. Save $20 on sessions for Premium.ML Mock & Coaching now available
NEW: ML Mock & Coaching with a 20+ year experience coach. Save $20 on sessions for Premium.ML Mock & Coaching now available
The fundamentals prequel to Batch Inference at Scale - from the moment you hit enter down to the GPU's memory system. Prefill vs decode, the KV cache, continuous batching, and the scaling signals that actually matter — the five facts that answer every deep-dive follow-up.
“How LLM Inference Actually Works” is free with an account. Your progress and bookmarks follow you across devices.
Sign in to continueYou hit enter. Roughly 300 milliseconds later the first word appears, and then tokens arrive at about 30 per second. Between those two moments sits one of the more interesting systems running in production today.
Scope contract. This page goes from the moment you hit enter down to the GPU's memory system. It does not go down to CUDA kernels. If you want the system-design layer above this — capacity planning, multi-region, 10k RPS — that's the Batch Inference System question. If you want kernel-level work, that's a different document and a different job description.
Who this is for. Engineers preparing for senior/staff interviews at AI labs, where "design an LLM API" is now a standard question and the deep-dive round goes exactly one level below the API. That level is what's written down here.
Most engineers can draw the boxes: client → gateway → router → GPU fleet. That gets you through the first fifteen minutes of an interview. What separates candidates is what happens when the interviewer asks the follow-up:
Every one of those questions is answered by the same small set of facts about how a transformer actually executes at inference time. There are maybe five of them. This page is those five facts, plus the vocabulary to state them cleanly under pressure.
One honesty note, because it matters for how you use this: understanding these mechanics is not the same as having built vLLM. Interviewers know the difference, and they reward first-principles reasoning over recited internals. The goal here is that when someone pushes one level below your architecture diagram, you have somewhere to stand.
The single most useful thing to internalize is that your data changes shape four times on the way through:
text → token IDs → K,V tensors → text deltas → SSE frames
Each arrow is a component boundary, and almost every production problem lives at one of them.
| One Request — The Ten Steps | ||
|---|---|---|
| # | Step | What actually happens |
| 1 | Client request | POST /v1/messages with stream: true. The connection stays open for the whole generation. |
| 2 | Gateway | TLS termination, auth, quota and rate-limit checks, schema validation. Holds the open connection for the request's entire lifetime. |
| 3 | Route | Router picks an engine replica using a live load view — and, if it's good, prefix affinity (see Scaling below). |
Steps 1–7 happen once per request. Steps 8–10 — the green path — run once per output token.
A 500-token response runs that green loop 500 times. Everything about inference performance follows from the fact that one part of the system runs once and the other part runs hundreds of times, and that these two parts are bottlenecked on completely different hardware resources.
That's the physics section below. First, some concrete numbers.
Six words. Seven tokens:
| Tokenization of the Example Sentence | ||
|---|---|---|
| # | Token | Note |
| 0 | I | |
| 1 | ␣got | leading space is part of the token |
| 2 | ␣an | |
Two things worth saying out loud, because they surprise people and they have real consequences:
Leading spaces belong to the token. ␣got and got are different token IDs. This is why prompt formatting — a trailing space in a template, say — can measurably change model behavior.
Rare and compound words fragment. BPE builds a fixed vocabulary (~100k–200k entries) from frequent byte sequences. "OpenAI" isn't frequent enough to earn its own entry, so it becomes ␣Open + AI. The practical consequence: you cannot bill, budget, or capacity-plan in words. Non-English text and code fragment much harder — a rule of thumb of ~1.3 tokens/word for English prose can go to 2–3× for languages that don't use Latin script.
Now the part that matters for systems. Picture a grid:
Each cell holds the K and V tensors for that (layer, token) pair. Prefill fills the entire grid in one pass. Every subsequent decode step appends exactly one new column, all 80 rows.
For our running example model — 80 layers, 8 KV heads under GQA, head dimension 128, fp16:
per layer, per token: 2 × 8 × 128 × 2 bytes = 4 KB
per token (80 layers): 4 KB × 80 = 320 KB
this sentence: 320 KB × 7 tokens = 2.24 MB
2.24 MB of GPU memory for one seven-token sentence. Hold that number; the physics and continuous batching sections are both consequences of it.
Being able to produce this arithmetic live is a real differentiator in an interview. It's the difference between a candidate who read a blog post and one who can do napkin math on the whiteboard. The full formula, with more worked cases, is in Appendix A below.
| 4 | Queue | The request waits at the engine for admission. This wait is invisible in GPU metrics and is very often where your latency actually is. |
| 5 | Tokenize | Text → integer token IDs via BPE. First shape change. |
| 6 | Admit | The scheduler allocates KV cache blocks and adds the sequence to the running batch. Admission is a memory decision, not a compute decision. |
| 7 | Prefill | One forward pass over ALL prompt tokens at once. Fills the KV cache and produces the first output token. This is your TTFT. |
| 8 | Decode step | One forward pass produces exactly one token, and appends one column to the KV cache. Repeat. |
| 9 | Detokenize | Token IDs → text deltas, incrementally. Has to handle tokens that are partial UTF-8 sequences. |
| 10 | Stream | Each delta goes out as an SSE frame, back through the gateway, to the client. On EOS or max_tokens, the sequence finishes and its KV blocks are freed. |
| 3 |
␣offer |
| 4 | ␣from |
| 5 | ␣Open |
| 6 | AI | "OpenAI" splits in two |