See It Flow

AI Infrastructure · Module 1

AI Infrastructure Overview

Understanding the systems that power modern AI applications.

Mangesh MandlikLast updated:

Visual Experience

What Happens Behind ChatGPT?

Follow a single question from a chat box all the way down through a typical AI serving stack: the application, the model, the compute cluster, and the serving and monitoring systems that make the answer possible. ChatGPT is only a familiar entry point: the stack shown is a generic, illustrative architecture, not a description of OpenAI's actual systems.

AI Infrastructure · Module 1

AI Infrastructure Overview

Understanding the systems that power modern AI applications

Mute narration
1 / 30

01 ·User Opens ChatGPT

A user opens ChatGPT.

📨open
🔁request
⚙️tokens
🧑

User

asks for help

💬

Chat App

application layer

🧠

LLM

answer generation

✨

Response

visible output

🧑Open ChatGPT

User Opens ChatGPT

Each step shows a cause, the process it triggers, and its effect on the system.

"It starts with something tiny: a person opening ChatGPT."

Previous scene
Play
Next scene
Mute narration
Replay from Scene 1

AI Infrastructure Architecture: What It Is, and Where It Starts and Stops

What is AI infrastructure? It is the compute, storage, networking, data pipelines, serving layer and observability that let a model be built, run and kept healthy. Beyond the model's mathematics, that means the accelerators that execute it, the memory and storage that hold its weights and data, the networks that move tensors and requests, the registry that versions model artifacts, the runtimes and endpoints that answer requests, and the security, monitoring and cost controls wrapped around all of it. Its architecture is organised around two lifecycles, an offline lane that produces a versioned model artifact (data, training, evaluation) and an online lane that turns that artifact into answers for live users (serving, inference, operations). The two lanes meet at one object, the model artifact in a registry.

Not every application operates all of it. A team that calls a hosted LLM API owns the application, its data and its policies, and rents everything below the API; a team that deploys its own model also owns the endpoint, runtime, accelerators and their failure modes. Training is done by far fewer organisations than inference. This chapter maps the whole AI infrastructure stack using one support question, then one training job, then the bytes and the milliseconds, so that the twelve specialist lessons that follow each have an obvious place to attach.

Following One Support Question Through the Stack

Running example for the whole track: an enterprise support assistant. A customer success agent at a tenant called acme types, "Can a customer with a duplicate charge get an automatic refund in the EU?"and presses Enter. Walk through what has to happen before the first word appears. The browser sends an authenticated HTTPS request to an API gateway, which validates the session token, rate-limits the tenant and forwards the call to the application's orchestrator. Everything up to here is ordinary web infrastructure and has nothing specific to AI.

The orchestrator is the application's own service, and it does the work that makes an answer grounded. It embeds the question, searches the tenant's document index with an authorisation filter so that only documents this user may read are candidates, and assembles a prompt from the system instructions, the retrieved passages and the question. If the question also asked about a specific order, the orchestrator would call an order-lookup tool under the user's permissions. A language model cannot see live transactions unless some authorised code fetches them and puts the result in the prompt; the model only ever receives text.

Only then does the prompt cross into model-serving territory: a request to a model endpoint, which may be a provider's API or your own service. That endpoint queues the request, an inference runtime tokenises the prompt, runs prefill (processing the whole prompt in parallel to produce the first token), then decode (generating the remaining tokens one step at a time) on an accelerator, and streams tokens back as they are produced. Every hop emits traces, token counts and costs to the observability system. The figure shows the same trip as a sequence; the dividing line between "application services" and "model-serving services" is the fifth lifeline, and moving that line is the main infrastructure decision this chapter discusses.

One support question, from browser to streamed answerNine numbered messages across seven participants. The browser calls the gateway, which forwards identity to the orchestrator; the orchestrator retrieves tenant-authorised passages, sends a prompt to the model endpoint, and the inference runtime streams tokens back through the orchestrator to the browser while telemetry is recorded.BrowserAPI gatewayauth, quotasOrchestratorapp serviceRetrievalindex + ACLModel endpointserving tierRuntime + GPUprefill, decodeTelemetrytraces, tokens1. POST /ask + token2. tenant=acme, user claims3. query + ACL filter4. 4 passages5. prompt, stream=true6. queue, batch slot7. tokens (stream)8. SSE chunks9. trace, token counts
One support question, from browser to streamed answer. The orchestrator is the application; the model endpoint and everything right of it is model serving. With a hosted API, the last two lifelines live inside the provider.
Two different meanings of 'the model service'
When engineers say the system is slow they often mean different tiers. Retrieval latency, tool latency and orchestration code belong to the application; queue wait, prefill and decode belong to model serving. The timing trace later in this chapter separates them so that you can tell which team's dashboard to open.

Defining the Stack by What Has to Be Done

A definition by layers ("hardware, software, platform") hides the useful question: which concrete jobs does a team have to do for a model to serve traffic? There are ten, and they are best remembered by the failure each one prevents.

Compute executes the arithmetic. Training and large-batch work are throughput problems; interactive inference adds latency requirements. Memory decides what fits: weights, optimiser state, activations and the per-request attention cache all have to be resident in fast accelerator memory while the model runs, so a model that is too big simply does not start. Storage holds datasets, checkpoints and the artifact registry, and has to stream data fast enough to keep accelerators busy. Networking carries user requests, but in distributed training and multi-accelerator serving it also carries tensors between devices, which makes it part of the compute path rather than plumbing.

Data pipelines turn raw text and documents into training sets, evaluation sets and, for retrieval, indexed chunks; most model-quality failures trace back here. Model artifacts are the versioned bundle of weights, tokenizer and configuration with an identity you can pin and roll back. Inference runtimes are the software that loads those weights and executes them efficiently with batching and caching. Serving endpoints wrap runtimes with an API, health checks, routing, versioning and autoscaling. Security covers tenant isolation, secrets, what may be sent to which model, and what a tool may do. Monitoring and cost governance make quality, latency and spend visible, because token-priced or GPU-hour-priced systems can fail quietly by becoming expensive rather than by erroring.

Which of these a given team must own depends on how it consumes the model. A hosted-API consumer still owns data pipelines for retrieval, security of what it sends, application-level monitoring and cost tracking, and has no accelerators, no runtime and no registry of weights to worry about. A self-hosting team owns all ten. A team that fine-tunes an open model and serves it owns the offline lane as well. Reading the rest of this chapter, keep asking "which of these is mine?"; the hosted-versus-self-hosted section answers it concretely.

The infrastructure also does not include the model's knowledge. Weights encode patterns from training data and have a cutoff; what the assistant knows about this week's refund policy lives in your document index and arrives through the prompt. For why that matters see Why RAG Exists, and for the limits of what a prompt can hold see Context Window.

Two Lifecycles That Meet at the Model Artifact

The most common conceptual error about AI infrastructure is to picture one pipeline in which data goes in one end and answers come out the other. There are two systems with different clocks, different owners and different failure costs. The offline lane runs for hours to weeks, is judged by model quality and cost per run, and tolerates being paused or restarted from a checkpoint. The online lane runs continuously, is judged by latency, availability and cost per request, and a minute of downtime is visible to users. They share hardware vendors and some libraries, but almost nothing operationally: a training cluster that is idle at night is not serving customers, and a serving fleet is rarely able to train.

Two-lane architecture: offline model building and online inferenceThe top lane runs left to right from data sources through cleaning, tokenisation and sharding, distributed training workers and an evaluation gate. The bottom lane runs from client through gateway, queue and scheduler, inference runtime and accelerator replicas. A model registry sits between the lanes: the evaluation gate publishes versioned artifacts to it, and serving replicas load weights from it.OFFLINE LANE: build the modelData sourcesdocs, logs, labelsClean + dedupefilters, PIITokenise + shardtraining setTrain workerscheckpointsEvaluation gatequality, safetyModel registryweights + tokenizer + configONLINE LANE: serve the modelClientchat, APIGatewayauth, quotaQueue + batchschedulerRuntimeprefill, decodeGPU replicasweights in HBMpublishload weights
Two-lane architecture: offline model building and online inference. Training never talks to users and serving never trains. The registry entry is the only contract between them: if weights are not in the registry with a version and a digest, serving cannot use them.

The artifact is the handshake. What serving needs from training is small and precise: the weights in a stated numeric format, the tokenizer (a different tokenizer silently changes what the same bytes mean), the model configuration, and metadata saying which data, code and evaluation produced it. A registry entry makes that bundle immutable and addressable by version and content digest, so that "roll back to the previous model" is an operation rather than an archaeology project. Hosted-API consumers still have this object; it just lives in the provider's registry, and the version you pin in an API call, when the provider supports pinning, is your only handle on it.

Model artifact lifecycleA checkpoint is evaluated, packaged with tokenizer, configuration and a content digest, registered, staged for a load test, canaried on a small share of traffic and promoted to production. A failed gate leads to rejected; a canary that breaches latency or quality limits leads to rolled back; a promoted version is eventually retired when superseded.Checkpointstep 2346Evaluatedgate passedPackageddigestRegisteredversionedStagedload testCanary5% trafficProduction100%Rejectedkept for auditRolled backprevious pinnedRetiredsupersededfails gateSLO breach
Model artifact lifecycle. Each transition is a decision with an owner and a recorded reason. The registered state is where training's responsibility ends and serving's begins.

Two details of this lifecycle matter for infrastructure. First, a checkpoint is not an artifact. A training checkpoint carries optimiser state needed to resume training and is several times larger than the weights needed for inference; the next section works through the numbers. Second, the canary state exists because offline evaluation cannot reproduce production traffic: real prompts are longer, noisier and more adversarial than the evaluation set, and the first place the version meets them is the small slice of traffic you chose to expose. Model Serving covers the rollout mechanics.

The Offline Lane: One Training Job From Raw Text to Checkpoint

Here is a deliberately small, illustrative job, a full fine-tune of an 8-billion-parameter open model on support transcripts, so that every stage of the offline lane has a duration and a size. All numbers are assumptions for teaching, not measurements. The dataset is 50,000 example conversations averaging 600 tokens after tokenisation. That is 50,000 × 600 = 30 million tokens per pass over the data (an epoch), and three epochs process 90 million tokens. With a global batch of 64 sequences, each step consumes 64 × 600 = 38,400 tokens, an epoch takes ⌈50,000 / 64⌉ = 782 steps, and three epochs take 2,346 steps.

Suppose the cluster delivers 20,000 training tokens per second end to end; delivered, not peak, since data loading, communication and idle gaps all reduce it below any hardware datasheet. Then pure compute time is 90,000,000 / 20,000 = 4,500 s = 75 minutes, about 1.92 s per step (38,400 / 1.92 ≈ 20,000). The stages around training are not free: ingesting and cleaning the raw transcripts (removing duplicates, redacting personal data, filtering low-quality examples) is assumed to take 40 minutes, tokenising and sharding 15 minutes, and after training an evaluation run of 10 minutes and a registration step of 5 minutes.

Illustrative fine-tuning job, stage by stage (minutes)Ingest and clean from minute 0 to 40, tokenise and shard 40 to 55, train 55 to about 134 including four synchronous checkpoints, evaluate 134 to 144 and register 144 to 149. Training dominates, but data preparation and evaluation account for nearly half of wall-clock time.0255075100125150minutesIngest + clean40Tokenise + shard15Train (2,346 steps)75 + 3.7 ckptEvaluate10Package + register5
Illustrative fine-tuning job, stage by stage (minutes). Wall-clock is 149 minutes of which 75 are productive training compute (50%). Improving the training step alone cannot shrink the other half.

The checkpoint arithmetic explains both the pause in the timeline and the difference between a checkpoint and an artifact. A common mixed-precision recipe with the Adam optimiser stores 2 bytes per parameter for 16-bit weights plus 12 bytes for optimiser and master state (a 32-bit master copy and two 32-bit moment estimates), about 14 bytes per parameter in total. For 8 × 109 parameters that is 112 GB (decimal; 104.3 GiB) per checkpoint, of which only the weights, 16 GB (14.9 GiB), are needed to serve. Checkpoints are written every 500 steps, at steps 500, 1,000, 1,500 and 2,000. If a checkpoint is written synchronously to storage that sustains 2 GB/s, each one stalls training for 112 / 2 = 56 s, so four of them cost 224 s ≈ 3.7 minutes, the reason the training bar is 79 minutes rather than 75. (Real systems overlap writes with compute and shard them across workers; that trade-off is a training-lesson topic.) The artifact published to the registry is the 16 GB of weights plus tokenizer and configuration, not 112 GB.

Why does a job need checkpoints at all? Because at scale something fails during a run: a node, a network link, a data shard that cannot be read. Without a checkpoint, a failure at step 2,300 restarts at step 0; with them, it loses at most 500 steps, about 16 minutes at 1.92 s per step. That reasoning grows steeply with cluster size and run length, which is why distributed training has its own failure-handling machinery. For the mechanics of data, tensor and pipeline parallelism, gradient exchange and optimiser sharding see Training Infrastructure and Parallel Processing.

Most teams never run this lane
Pre-training a large model from scratch is an operation measured in thousands of accelerators and months; the small job above is closer to what an application team might do, and many teams do neither, consuming a model trained elsewhere. The offline lane still matters to them: it is where the model they consume came from, and the provider's choices about data, evaluation and release cadence show up as behaviour changes in their application.

The Online Lane: Queue, Prefill, Decode and What 'Throughput' Means

Inference serves one request at a time from the user's point of view, but the system is built around serving many at once. The reason is the shape of the work. Prefill processes all prompt tokens together, so it involves a great deal of arithmetic per byte of weights read and keeps the accelerator's compute units busy. Decode then generates one new token per step per request, and each step has to read essentially the whole set of model weights from accelerator memory to produce a single token for a single request. That is far less arithmetic per byte, so decode is typically limited by memory bandwidth, not compute. The remedy is batching: if sixteen requests are in decode simultaneously, one pass over the weights produces sixteen tokens, one per request, and the cost of reading the weights is shared.

This is why serving systems have a scheduler between the endpoint and the GPU. It admits requests into the running batch as slots free up (continuous batching), keeps per-request attention state (the KV cache, whose memory cost grows with prompt and output length) in accelerator memory, and decides who waits when memory is short. The details of that are the subject of Inference Infrastructure; what you need here is the vocabulary of performance, because three different numbers get called "throughput" and they are not interchangeable.

Token throughput is output tokens per second across the replica. Request throughput is completed requests per second, which depends on how many tokens each request produces. Per-stream speed is the tokens per second one user sees, the inverse of inter-token latency. Take the illustrative replica used in the timing trace below: a batch of 16 concurrent streams, each emitting a token every 20 ms (50 tokens/s per stream). Token throughput is 16 × 50 = 800 tokens/s. If requests average 200 output tokens, the decode-side ceiling is 800 / 200 = 4 requests/s. A request lasts about 4.33 s, so Little's law (average number in the system = arrival rate × time in system) gives 4 × 4.33 ≈ 17.3 concurrent requests, more than the 16 slots, so the slots, not the GPU's arithmetic, are the binding limit: 16 / 4.33 ≈ 3.7 requests/s. And that still ignores prefill, which competes for the same GPU. A burst of long prompts can slow every active stream's token cadence. Peak throughput numbers measured with ideal batches therefore tell you little about the p95 latency a customer actually sees; the capacity of the service is what you can sustain while still meeting the latency objective, found by load testing with realistic prompt and output lengths.

The figure below recomputes that example. At 16 streams and 200 output tokens it reproduces the 4 requests/s ceiling and 3.7 requests/s slot-bound rate; change either control to see which limit binds first.

16
200
Three meanings of throughput for one replicaWith 16 concurrent streams at 50 tokens per second each, token throughput is 800 tokens per second. For 200-token answers the decode-only ceiling is 4.0 requests per second, but each request occupies a slot for 4.33 seconds, so 16 slots complete 3.7 requests per second. Running at the ceiling would need 17.3 slots, more than the 16 available.Requests per secondLittle's law: slots heldDecode-only ceiling4.0 req/sSlot-bound rate3.7 req/sSlots needed at ceiling17.3 slotsSlots available16 slots
Three meanings of throughput for one replica. With 16 concurrent streams at 50 tokens per second each, token throughput is 800 tokens per second. For 200-token answers the decode-only ceiling is 4.0 requests per second, but each request occupies a slot for 4.33 seconds, so 16 slots complete 3.7 requests per second. Running at the ceiling would need 17.3 slots, more than the 16 available.
Token throughput
800 tok/s
16 × 50 per stream
One request lasts
4.33 s
0.35 + 199 × 0.02
Decode-only ceiling
4.0 req/s
800 ÷ 200
Slot-bound rate
3.7 req/s
16 ÷ 4.33
Request rate is the wrong unit for LLM capacity
Two services with identical request rates can need very different fleets if one produces 50-token answers and the other 1,000-token answers, or if prompts are 300 tokens in one and 12,000 in the other. Plan in input tokens per second (prefill load), output tokens per second (decode load) and concurrent streams (memory load), and keep requests as the unit users care about.

Where the Bytes Live and How They Move

A single mental picture clears up most confusion about "where the model runs": a hierarchy of places that hold bytes, each faster and smaller than the one before it. Model weights begin in object storage, a durable network-attached store. To serve them, a replica copies them across the network to a local NVMe disk or directly into host RAM, then across the host's PCIe bus into the accelerator's high-bandwidth memory (HBM, also called VRAM for GPUs), where the compute cores can use them. The CPU is not idle in this picture; it runs the orchestration, the tokeniser, the scheduler and the code that launches accelerator kernels. The accelerator does the dense arithmetic. Multi-accelerator deployments add a fourth path: a fast interconnect between devices that carries partial results when one model is split across several of them.

Memory and network data movement for one replicaWeights path, once per replica start: object storage over the network to a local NVMe SSD, then host RAM, then across PCIe into GPU HBM, then through the memory bus to compute cores, with an interconnect to other GPUs. Request path, on every request: client network interface to the CPU runtime, which tokenises and launches work on the GPU. Bandwidth labels are illustrative round numbers.Weights path: once per replica startObject storedurable, remoteLocal NVMecache of weightsHost RAMCPU sideGPU HBMweights + KV cacheCompute coresmatrix unitsRequest path: on every requestNetwork inprompt text, ~12 KBCPU runtimetokenise, scheduleOther GPUssame model split1.25 GB/s3 GB/s25 GB/s2,000 GB/stoken IDs, kernelsinterconnect
Memory and network data movement for one replica. Illustrative bandwidths (decimal GB/s) to show orders of magnitude, not any product's specification: each step toward the compute cores is much faster, and much smaller, than the one before.

Put numbers on it with the same 8-billion-parameter model in 16-bit precision: 8 × 109 parameters × 2 bytes = 16 GB in decimal units, 14.9 GiB in binary. Loading from remote storage over an effective 10 Gbit/s (1.25 GB/s) link takes 16 / 1.25 = 12.8 s; from a local NVMe disk at an assumed 3 GB/s, 5.3 s; and the final hop across PCIe at an assumed 25 GB/s is 0.64 s. These are the cold-start costs that decide how quickly an autoscaler can add a replica: if the weights are not already on local disk, a new replica is not useful for at least the network-limited 12.8 s plus runtime start-up, which is why a spike can overwhelm a service before new capacity arrives, and why model-serving systems keep weights close to the node.

Now consider what happens per request. The prompt is text, a few kilobytes: 3,000 tokens as 4-byte integer IDs is 12 KB. That is negligible next to 16 GB. Weights do not travel with each request; they already sit in HBM, and the request moves to the weights. The expensive movement is inside the GPU: each decode step reads the full weights from HBM. At an assumed 2,000 GB/s, 16 GB / 2,000 GB/s = 8 ms is a lower bound on one decode step, regardless of how fast the arithmetic is. The 20 ms per step used in this chapter's trace is above that bound because real steps also read KV-cache data, launch many small kernels, run sampling and scheduling, and never reach peak bandwidth. The gap between a datasheet bound and an observed number is the room where runtime engineering lives.

Prefill is the reverse case. Counting roughly 2 floating-point operations per parameter per token for a dense transformer's forward pass (ignoring the attention term), a 3,000-token prompt costs about 2 × 8 × 109× 3,000 = 4.8 × 1013 operations. If prefill takes 200 ms, the delivered rate is 2.4 × 1014operations per second, 240 TFLOP/s. Whether that is plausible depends on the accelerator; what matters is that it should be compared with measured delivered throughput on your stack, never with a theoretical peak, because kernel efficiency, memory stalls and precision all push delivered below peak. Prefill is bound by compute and decode by memory bandwidth, and that one fact explains why a single GPU can look underused during decode while users still wait: arithmetic units idle while HBM is saturated.

Which bottleneck binds also depends on scale. Within one accelerator, memory capacity (does the model plus its caches fit?) and bandwidth dominate; across accelerators, the interconnect starts to matter; across machines and regions, network latency and bandwidth do. A model too large for one device must be split, and every split turns some memory traffic into network traffic. Accelerator internals, their memory hierarchies and the choice between them are the subject of CPUs vs GPUs vs TPUs and AI Accelerators.

Hosted API or Your Own Replicas: What Actually Changes

When you call a provider's LLM API, the physical infrastructure above does not disappear; it becomes someone else's. Their data centres hold accelerators, their schedulers batch your request with other customers', their registry holds the model version you named. The abstraction removes operational work, not physics: your request still waits in a queue, still goes through prefill and decode, and latency still varies with load. What the abstraction changes is which of the failures and costs are yours to handle.

Who operates each layer: hosted API versus self-hosted modelNine layers from application code down to the facility. Green cells are yours to build and run. Grey cells are operated by an API provider. Blue cells are rented capacity operated by a cloud or colocation provider. The application, retrieval, tenant authorisation and quota policy are yours in both columns; the model tier is the part that moves.Hosted LLM APISelf-hosted modelApplication, prompts, toolsyou build and ownyou build and ownRetrieval, tenant ACLs, datayou own; data leaves to APIyou own; data stays in VPCQuotas, retries, fallbacksyou add; provider limits applyyou build the full policyEndpoint, routing, autoscalingprovider operatesyou operateModel weights and versionsprovider ships versionsyou choose, store, verifyInference runtime, batchingprovider operatesyou configure and tuneGPU / accelerator capacityprovider owns and sharesyou rent or buyFacility, power, hardwareprovider (and its cloud)cloud / colo operatesTelemetry of the model tieronly what the API exposesfull, you build it
  • You operate
  • API provider operates
  • Cloud / colocation operates, you rent
Who operates each layer: hosted API versus self-hosted model. Nine layers from application code down to the facility. Green cells are yours to build and run. Grey cells are operated by an API provider. Blue cells are rented capacity operated by a cloud or colocation provider. The application, retrieval, tenant authorisation and quota policy are yours in both columns; the model tier is the part that moves.

Read the figure down the columns. In both, the top three rows are yours: the application that builds prompts, retrieval with tenant-level authorisation, and the policy for quotas, retries and fallbacks. These are never outsourced by buying an API. Moving from hosted to self-hosted turns the next five rows green: you now run the endpoint, pin and verify the weights, tune the runtime, obtain accelerator capacity and instrument the model tier. The two bottom rows stay with a cloud or colocation provider unless you run your own data centre.

The security and data consequences are not symmetrical. With a hosted API, prompts containing customer policies and, in the order-lookup case, customer data leave your network, so contract terms, data retention settings and regional processing options are part of the design. Self-hosting inside your network keeps those bytes in your boundary but adds exposure of its own: model weights are an asset to protect, the inference endpoint is an attack surface, and you are responsible for patching the serving stack. AI Security goes further.

Cost behaves differently too, and an illustrative calculation shows how. Take the support assistant at 100,000 requests per day with 3,000 input and 200 output tokens each. Assume a fictional API price of $1 per million input tokens and $4 per million output tokens. One request costs 3,000 × $1 / 106 + 200 × $4 / 106 = $0.003 + $0.0008 = $0.0038, or $380 per day. Assume instead two self-hosted GPU replicas (two for redundancy) at a fictional $2.50 per GPU-hour, always on: 2 × $2.50 × 24 = $120 per day, or $0.0012 per request at 100,000 requests/day. At the replica's modelled 3.7 requests/s, two replicas can serve about 7.4 requests/s, and the average load of 100,000 / 86,400 = 1.16 requests/s is only 16% of that; if the daily peak is three times the average, 3.5 requests/s is 47%.

Read that carefully before concluding self-hosting wins. The $120 excludes engineers who operate the fleet, on-call, evaluation of the model against a hosted frontier model, the cost of idle headroom for failures and spikes, storage, networking and the quality gap if the self-hosted model is less capable. The hosted figure scales to zero when traffic does; the fleet does not. Break-even depends on sustained utilisation, quality requirements, and how much the team values control, which is why the evolution path below starts with the hosted option and moves only when measurement says so. Cost Optimization treats this decision properly.

Timing One Request: Time to First Token and Total Latency

Now put timestamps on the sequence from earlier. Every number below is an illustrative assumption, measured from the moment the request reaches the gateway, so the user's network round trip (perhaps another 30 to 80 ms) is excluded. The model is self-hosted on the replica described above. The prompt is 3,000 tokens: system instructions, four retrieved passages and the question. The answer is 200 tokens.

Illustrative request timeline from gateway ingress (milliseconds)Gateway and authentication 0 to 25 ms; query embedding 25 to 45; vector search with access filter 45 to 85; prompt assembly 85 to 95; network and queue wait 95 to 135; tokenisation 135 to 140; prefill 140 to 340; first token delivered at 350; decode of tokens 2 to 200 from 340 to 4,320; last token delivered at 4,330 ms.035010002000300040004330msGateway + auth25Embed query20Vector search + ACL40Prompt assembly10Network + queue wait40Tokenise5Prefill (3,000 tokens)200First token deliveredTTFT = 350Decode tokens 2 to 200199 × 20 msLast token delivered4,330
Illustrative request timeline from gateway ingress (milliseconds). Time to first token is the sum of everything before the first generated token reaches the client. Total latency is dominated by decode, which scales with answer length.

TTFT (time to first token) is the sum of the stages that must finish before any answer is visible: 25 (gateway) + 20 (embedding) + 40 (search) + 10 (assembly) + 40 (network and queue) + 5 (tokenise) + 200 (prefill) + 10 (delivery of the first token) = 350 ms. Retrieval, at 60 ms, is 17% of it; prefill is 57%, and prefill scales with prompt length, so retrieving six passages instead of four (say, a 4,500-token prompt) would raise it by about 100 ms at the same implied rate of 15,000 prompt tokens/s (3,000 / 0.2 s). Queue wait is 11% and is the term that explodes under load: a replica running at its limit turns 40 ms into seconds.

Total latency adds decode. The first token is produced at the end of prefill, at 340 ms. The remaining 199 tokens each take a 20 ms step, 199 × 20 = 3,980 ms, so the last token is sampled at 340 + 3,980 = 4,320 ms and delivered at 4,330 ms. The visible streaming rate after the first token is 1 / 20 ms = 50 tokens/s, faster than most people read, so streaming makes the answer feel responsive even though completion takes 4.3 s. This is also why the two numbers need separate objectives. A service level objective on TTFT protects against queueing and long prompts; one on inter-token latency protects against batch saturation; a total-latency objective needs an assumption about output length, since doubling the answer to 400 tokens makes total latency 340 + 399 × 20 + 10 = 8,330 ms with an unchanged TTFT.

The same trace with a hosted API replaces the segments from "network + queue wait" through "prefill" with a single remote call whose internals you cannot see. You still measure TTFT and total latency at your own edge, and you still own the retrieval stage, which an API provider's status page never explains. Percentiles matter more than the average here: the trace is a single request, the p50 of a healthy service. If one request in twenty hits a cold cache, a long prompt or a full queue, the p95 can be several times the trace's figures, and users judge the service by the slow ones.

When Parts Fail: Reliability Boundaries

The multi-tier path above has a long series of dependencies, and reliability comes from deciding in advance what each failure means to the user. A principle that avoids most bad designs: degrade by being less capable and honest about it, never by being silently wrong. For a policy assistant, an answer produced without retrieved policy text is worse than no answer, because the model will still produce confident, fluent text, as described in Hallucinations.

Failure handling along the request pathThe request path runs from client through gateway, retrieval and tools, model endpoint, and streaming back. Four failure boxes hang below: quota exceeded at the gateway returns 429 with retry-after; retrieval or tool failure returns an honest limited answer or refusal; model overload sheds load or falls back; a replica dying mid-stream is retried if no tokens were sent, otherwise ends with an error event.ClientGatewayauth, quotaRetrieval + toolsModel endpointStream to userQuota exceeded429 + retry-afterIndex or tool downlimited answer or refuseModel overloadedshed, queue cap, fallbackReplica diesretry or error event
Failure handling along the request path. Each failure is detected at the tier where it happens and surfaced in a way the user can act on.

Retrieval fails. The vector index times out after 2 seconds. The orchestrator should not send the question to the model as if nothing had happened. It can retry once within a budget (the TTFT budget is shared, so a retry that costs 2 s may breach the objective), then either answer with an explicit "I could not check the policy documents" or refuse and offer a support ticket. If the assistant has a non-policy mode, such as drafting a customer email, that mode may continue without retrieval. The order tool failing is milder: answer the policy half and say that live order status is currently unavailable. The model must be told, in the prompt, that the tool failed; otherwise it will fill the gap with plausible text. Tools and Tool Calling covers the contract.

The model service is overloaded. Requests accumulate in the queue; each added request lengthens the wait of every one behind it, so latency climbs until timeouts start, at which point clients retry and make it worse. Reliable systems put a bound on queue depth, reject early with a retry hint rather than accept work they cannot finish within the objective, and optionally route to a fallback: a smaller model, or a different provider, with the quality difference known and measured in advance. A fallback you have never evaluated is a gamble, not a plan.

A GPU replica dies. Capacity drops immediately, requests in flight on that replica are lost and the load balancer has to stop sending it new ones. What the user sees depends on timing. If no tokens have been streamed, the gateway can retry transparently on another replica, costing the prefill again. If tokens are already on screen, a transparent retry would repeat or contradict text the user has read, so the stream usually ends with an error event and the client offers to resume or retry. Replicas also die during start-up: a replica that is still loading its 16 GB for 12.8 s must not receive traffic, which is what readiness checks, as opposed to liveness checks, are for.

A provider or dependency is unavailable. This is the hosted-API analogue of a dead replica, with less visibility. Short timeouts, a circuit breaker that stops calling a failing dependency for a cooldown period, retries with backoff and jitter capped to a small number, and an explicit decision about whether a second provider is worth its integration and evaluation cost. Retries amplify: with three tiers each making three attempts, one user request can become 27 backend calls during an outage; budget retries at the edge and propagate a deadline instead.

Reliability is a user-visible contract as much as an engineering one. For the support assistant, the contract is: never present an ungrounded policy answer as grounded; always say what could not be checked; and never charge or modify an order as a side effect of a retried request. Write the contract down for each failure before building the mechanisms, then test it by injecting each failure. The scaling and observability lessons show how the same signals drive capacity decisions and diagnosis.

Control Plane, Data Plane, Locality and Where SLOs Are Measured

A useful way to lay out the whole system is to separate what moves per request from what changes the system's configuration. The data plane carries user work: gateway, orchestrator, retrieval, the model replicas and the tokens they produce. It has to be fast and highly available. The control plane decides what the data plane looks like: which model version is loaded where, how many replicas exist, which quotas and routes apply, when the document index is rebuilt. It can be slower and can briefly fail without dropping requests, provided that the data plane keeps running with its last known configuration. This distinction is what makes a rollout safe: the registry tells the rollout controller to load version v7 on two replicas, health checks pass, the gateway's route weights shift, and no request ever needed to talk to the registry.

Control plane versus data planeFour control-plane components sit above the data plane they configure. Policy and configuration set gateway quotas and routes; the index builder updates retrieval; the registry and rollout controller load a specific model version onto replicas; the autoscaler adjusts replica count from telemetry. The request path runs left to right along the data plane: gateway, retrieval, model replicas, and telemetry on the right.CONTROL PLANE: changes configurationPolicy + configquotas, routesIndex builderingest, versionRegistry + rolloutmodel versionsAutoscalerreplica countDATA PLANE: serves requestsGatewayenforces policyRetrievalserves indexModel replicasserve tokensTelemetryqueue, TTFT, cost
Control plane versus data plane. Dashed arrows are configuration and feedback; solid arrows carry requests. Telemetry feeds the autoscaler, so a metrics outage becomes a control-plane problem.

Three placement ideas follow from the byte-movement picture. Data locality: the prompt carries retrieved text and sometimes personal data, so the index, orchestrator and model should sit close together, both for latency and to avoid sending regulated data across regions. Each cross-region round trip costs tens of milliseconds; if the orchestrator in one region made two sequential calls (embedding and search) to a service in another with an assumed 70 ms round trip, that adds 140 ms to the 350 ms TTFT before any other change, a 40% increase. Model versioning: pin the version in every request path, log it in every trace, and treat prompts, indexes and tool schemas as versioned artifacts as well, because an answer can change when any of the four changes. Regional placement of GPU capacity is also a supply question, not only a latency one: accelerators may not be equally available in every region, and regional autoscaling can be limited by quota.

Where each objective is measured determines what it can detect. TTFT and total latency are measured at the edge the user sees, the gateway or client, since anything measured only inside the model server omits retrieval, queueing and the network. Queue wait, prefill time and inter-token latency are measured inside the serving tier to diagnose which part of the edge number moved. Retrieval latency and tool latency are measured by the orchestrator. Quality (groundedness, citation correctness, task success) cannot be read from latency metrics at all and needs sampled evaluation. Availability objectives are judged by the outcomes users experience, including honest degraded answers, which you have to decide whether to count as success. AI Observability works through this.

Build the Smallest Working System, Then Evolve It

The architecture diagrams so far show an end state that few teams need on day one. A better practice is to add each piece when a measurement justifies it. A typical growth path for the support assistant looks like the five steps below, and each step is a deliberate answer to a symptom rather than a milestone to reach.

  1. 1

    Prototype: a hosted LLM behind one endpoint

    One service calls a provider API with a system prompt and the user's question. No GPUs, no registry, no retrieval. Add the cheap basics now: timeouts, a per-tenant rate limit, logging of token counts and latency, and a recorded set of 30 to 100 representative questions to compare later changes against. Symptom that ends this stage: answers about your own policies are wrong or outdated.
  2. 2

    Add retrieval with authorisation

    Index policy documents with tenant and role metadata, filter by it at query time, and inject the passages into the prompt. Quality improves because the model now reads the policy; a new infrastructure problem appears, which is that the index is production data with its own freshness, access control and failure modes. See the retrieval pipeline and context injection.
  3. 3

    Add an authorised tool for live order data

    The orchestrator exposes an order-lookup function that runs with the signed-in user's permissions and returns a bounded, validated result. It adds a second dependency to the reliability budget and a second place for tenant-isolation bugs. Not every application needs it, and it does not make the assistant an autonomous agent; it is one function call under application control.
  4. 4

    Add caching, load balancing and observability when load demands

    When load tests or bills show repeated work, add layers deliberately: caching with tenant-scoped keys, and traces that tie each answer to a model, prompt and index version. Quotas per tenant protect the multi-tenant service from one customer's batch job.
  5. 5

    Self-host a model only when the numbers justify the work

    Reasons that justify it: data cannot leave your boundary, sustained utilisation makes dedicated capacity cheaper than tokens, you need a fine-tuned or specialised model, or a latency or regional requirement a provider cannot meet. Then the offline artifact, the runtime, the fleet and the failure modes above become yours. See Model Serving and Production AI Architecture.

One design choice makes the later steps cheaper: keep the model behind a narrow interface, so the orchestrator does not know whether tokens come from a provider or from your cluster. The sketch below is illustrative pseudocode in TypeScript, not a specific provider's SDK; real request shapes and streaming protocols differ by provider and must be taken from their documentation.

Illustrative pseudocode (TypeScript): a model interface that hides where inference runs
interface CompletionRequest {
  tenantId: string;
  model: string;           // a pinned model version, logged with every trace
  prompt: string;          // system text + retrieved passages + question
  maxOutputTokens: number; // bounds decode time and cost
  deadlineMs: number;      // remaining time budget, propagated from the edge
}

interface TokenChunk { text: string; done: boolean; }

interface ModelClient {
  stream(req: CompletionRequest, signal: AbortSignal): AsyncIterable<TokenChunk>;
}

// Composition: try the primary, fall back only before any token was emitted.
class FallbackClient implements ModelClient {
  constructor(private primary: ModelClient, private backup: ModelClient) {}

  async *stream(req: CompletionRequest, signal: AbortSignal): AsyncIterable<TokenChunk> {
    let emitted = false;
    try {
      for await (const chunk of this.primary.stream(req, signal)) {
        emitted = true;
        yield chunk;
      }
    } catch (err) {
      if (emitted) throw err; // the user already saw text: surface the error, do not splice
      yield* this.backup.stream(req, signal);
    }
  }
}

The orchestrator depends only on ModelClient. Switching to a self-hosted endpoint, or adding a fallback, changes composition, not application logic.

Note what the code encodes: the deadline travels with the request so every tier knows the remaining budget; output length is capped because it is the largest driver of both latency and cost; and fallback happens only before the first token, for the reason given in the reliability section.

What Comes Next: From the Map to the Machines

This chapter treated the accelerator as a box that holds weights and does arithmetic, and the stack around it as a set of jobs. Each remaining lesson takes one of those jobs and asks the next engineering question, and they group naturally by the problem you are trying to solve.

The natural next step is hardware: decode is limited by memory bandwidth and prefill by compute, so the processor's design decides what the stack above it can achieve. The next lesson compares the architectures that execute these workloads and why GPUs became the default.

Key Takeaways

  1. 1

    AI infrastructure is the compute, data, networking, serving and observability that surround a model; a team that calls a hosted API still owns the application, its data path, and its latency, cost and security boundaries.

  2. 2

    Two lifecycles meet at the model artifact: offline (data to training to checkpoint to artifact) and online (queue, prefill, decode). A checkpoint is not a deployable artifact until serving has what it needs in a stable format.

  3. 3

    When people say the system is slow they often mean different tiers (retrieval, tools, queue, prefill, decode), so measure each stage separately before blaming the GPU.

  4. 4

    Define TTFT as the sum of everything before the first token and total latency as TTFT plus decode; token throughput and request throughput differ, so a service with long answers needs a very different fleet at the same request rate.

  5. 5

    Decide in advance what happens when each dependency fails (retrieval timeout, overloaded model service, dead replica, provider outage), and carry the deadline with the request so each tier knows its remaining budget.

  6. 6

    Start with the smallest working system behind a narrow model interface and add machinery only when a measurement demands it; compare self-hosting against a hosted API on total cost including the engineers who would run it.

Up Next · AI Infrastructure

CPUs vs GPUs vs TPUs

AI models ultimately run on specialized hardware. In the next module we'll explore CPUs, GPUs, and TPUs, and understand why GPUs became the foundation of modern AI.