Track D — ML and Inference Infrastructure

The reported onsite design round was "design ChatGPT", with the interviewer caring about GPU allocation, autoscaling under non-stationary traffic, and distributed coordination (../../research/source-report.md rows 28–32). The reported advice was to abstract the model-serving layer unless told otherwise.

This is the round most senior generalists lose. It is also the one where your background transfers further than you would guess — see below.

→ Study guide: WARMUP.md — inference from zero: the KV cache, the roofline derivation, the memory budget, every batching technique, autoscaling, and a complete worked “design ChatGPT” answer at both altitudes.


Table of Contents


Why This Is Closer to Your Background Than It Looks

A decade on multilingual search and recommendation means you have shipped: a serving tier with a hard latency budget, an index that does not fit on one box, ranking under a compute constraint, cache hierarchies where hit rate is the whole economics, and traffic that is non-stationary by time zone.

Serving an LLM is the same problem class with three substitutions:

Search/rankingLLM serving
Index shards that must fit in RAMModel weights + KV cache that must fit in HBM
Cache hit rate drives costPrefix-cache hit rate drives cost
Fan-out then merge, bounded by the slowest shardPrefill then decode, bounded by memory bandwidth
QPS-based autoscaling worksQPS-based autoscaling fails — see D4
Tail latency from stragglersTail latency from queueing behind long prefills

The gap is vocabulary and the memory-bandwidth constraint, not concepts. That is roughly six weeks of focused work, not six months — which is why this track gets 20% of hours rather than 40%, despite being the round you are weakest in today.


The Two Altitudes

The reported advice — abstract the model-serving layer unless told otherwise — is a scoping test, not a hint about depth. This is inference I2 in ../../research/findings.md.

The interviewer wants to see whether you can identify which component is load-bearing for this conversation and hold the rest at a stable interface. Candidates who dive straight into PagedAttention are demonstrating knowledge while failing the actual signal, which is judgement.

Altitude 1 — abstracted (your default). Name the abstraction explicitly and move on:

"I'll treat the inference engine as a service with three properties: it exposes tokens-per- second capacity rather than requests-per-second, it has an admission interface I can apply backpressure to, and it streams. I'll spend my time on traffic, coordination, and failure — tell me if you want me to open it up."

That sentence does three things at once: it proves you know the engine is special, it hands the interviewer the steering wheel, and it buys you the time for the parts they asked about.

Altitude 2 — opened. When they say "open it up," you have seconds, not minutes, to get into KV cache math, batching policy, and scheduling. Hesitating there undoes the credibility the abstraction bought.

Drill both. Default to altitude 1.


The One Fact Everything Follows From

If you internalize one thing in this track, this is it.

Autoregressive decode is memory-bandwidth-bound, not compute-bound.

The derivation, which you should be able to do on a whiteboard in ninety seconds:

To generate one token, the GPU must read every weight in the model. For a 70B model at FP16 that is 140 GB of reads per token, per sequence in the batch — except that a batch shares the weight read. So:

time per decode step  ≈  bytes_of_weights / memory_bandwidth
70B FP16 on an H100:  140 GB / 3.35 TB/s  ≈  42 ms   (weights alone, one step)

Meanwhile the FLOPs for one token are ~2 × 70e9 = 140 GFLOP. An H100 does ~989.5 TFLOP/s dense dense BF16, so the compute takes ~0.07 ms. Three orders of magnitude apart. The GPU is idle waiting on HBM.

Three consequences, and every technique in this track is one of them:

  1. Batching is nearly free on the compute axis — you amortize the same weight read across more sequences. This is why continuous batching is the single biggest throughput lever.
  2. Prefill is the opposite. Processing a 2,000-token prompt is a big matrix multiply: compute-bound, high arithmetic intensity. So prefill and decode want different scheduling, which is the entire reason chunked prefill exists.
  3. The KV cache, not the weights, is what limits your batch size. It grows linearly with batch size and sequence length, and it is why memory management is the hard part.

The clean empirical proof: the H200 has identical compute to the H100 — same 989.5 TFLOP/s BF16 dense, same 1,979 TFLOP/s FP8 dense — and 43% more memory bandwidth (4.8 vs 3.35 TB/s). It is materially faster at decode. If decode were compute-bound, it would be exactly as fast.

Being able to state this, derive it, and cite the H100/H200 comparison as the evidence is worth more in this round than knowing the name of every serving framework.


Concept Inventory

D1. Request Lifecycle

ConceptThe question it answers
Gateway, auth, quota, routingWhere does a request get rejected before it costs a GPU?
Model registry and version pinningHow does a conversation stay on one model version?
Context assembly: system prompt, history, tools, RAGWhat actually gets tokenized, and how big is it?
Tokenization, and where it runsCPU work on the critical path — batch it or move it
Prefill vs decodeTwo different workloads sharing one accelerator
TTFT vs TPOT vs end-to-endThree SLOs that trade against each other
Streaming transport: SSE vs WebSocketWhy SSE usually wins for one-way token streams
Abort handlingUser closes the tab — how fast do you stop paying for it?
Conversation stateStateless serving with client-supplied history, or server-side sessions?

D2. GPU Memory and Economics

ConceptThe question
Weights + KV cache + activationsThe memory budget, and what is left for batch
KV cache size formulaSee the calculator
GQA / MQA and their effect on KV sizeThe architectural lever that makes long context affordable
Quantization: FP16 / FP8 / INT8 / INT4What you trade and where quality actually breaks
Tensor parallelismSplit a layer across GPUs; needs fast interconnect every layer
Pipeline parallelismSplit layers across GPUs; introduces bubbles
Expert parallelism (MoE)Sparse activation; all-to-all becomes the bottleneck
Multi-tenancy and fragmentationWhy a 60%-full GPU can refuse a request
Cold start and weight loadingMinutes, not seconds — which is why warm pools exist
Spot vs reserved capacityPreemption on a stateful decode is expensive
Cost per million tokensThe number the business actually runs on

D3. Throughput Techniques

Each with what it buys, what it costs, and when it loses.

TechniqueBuysCostsLoses when
Continuous batching (Orca)Huge throughput; no idle slotsScheduler complexityAlmost never — this is table stakes
PagedAttention (vLLM)Near-zero KV fragmentation; higher batchIndirection per attention opAlmost never
Prefix cachingSkips prefill for shared prefixesCache memory; eviction policyPrefixes are not shared
Chunked prefill (Sarathi)Much better TTFT tailSlightly lower prefill throughputThroughput matters more than tail
Speculative decodingLower latency at low batchWasted compute on rejects; a draft model to maintainHigh batch — you have no spare compute
QuantizationMore batch, more speedQuality, and it is workload-specificQuality is the product
Disaggregated prefill/decodeEach phase scales independentlyKV transfer across the networkThe transfer cost exceeds the win

The framing that makes this an answer rather than a list: these are not a stack of wins. They are points on a throughput-versus-tail-latency curve, and different traffic classes want different points. An interactive chat turn, a long agentic tool loop, and a batch API are three different curves. Saying that — and then asking whether they run separate pools or one priority-aware scheduler — is the staff-level move.

D4. Autoscaling Under Non-Stationary Traffic

Explicitly named by the interviewer in the source report. This is where your search background transfers and where it misleads you.

Why request-count autoscaling fails for LLMs. In a search tier, requests are roughly interchangeable, so QPS is a good proxy for load. In LLM serving, one request can be a 20-token prompt with a 5-token answer and another can be a 100k-token prompt with a 4,000-token answer. Their costs differ by four orders of magnitude. QPS-based HPA is measuring the wrong thing, and it will scale up on a burst of cheap requests and fail to scale on a handful of expensive ones.

SignalQualityWhy
Requests/secBadCost variance is 10,000x
GPU utilizationMisleadingDecode is bandwidth-bound; utilization can read high while throughput is poor
Queue depth / waiting timeGoodDirectly measures unmet demand
Tokens/sec (prefill + decode separately)GoodThe actual unit of work
KV cache occupancyGoodThe real capacity constraint; predicts admission failure before it happens
TTFT p95Good as an SLO triggerThe thing users feel

Also required:

  • Predictive vs reactive. GPU scale-up is minutes (allocation + weight load), so purely reactive scaling is always late. Forecast from historical diurnal patterns and pre-warm. The SageServe and ENOVA lines of work are exactly this.
  • Warm pools. Pay for idle capacity to hide cold start. Size it from the forecast error, not from average load.
  • Admission control and load shedding. When you cannot scale further, refuse work rather than accepting it and missing SLO for everyone. Little's law and the utilization knee are the argument.
  • SLO classes and fairness. Interactive, batch, and free-tier want different queues. Per-tenant fairness so one heavy user cannot starve the rest. Weighted fair queueing on tokens, not on requests.

D5. Distributed Coordination

ConceptThe question
Scheduler placementWhich replica gets this request, given its KV state and prefix cache?
Prefix-aware routingRoute to the replica that already has this prefix cached — a huge win, and it turns the load balancer into a cache-affinity problem you have solved before
Health, drain, and graceful shutdownDecode sequences in flight for minutes — you cannot just SIGTERM
Rolling model rolloutsTwo model versions live at once; conversations pinned to one
Canaries and shadow trafficEvaluating a new model without exposing users
Config propagationRate limits and routing rules updated without a restart
Global rate limitingPer-tenant quotas across regions; the same problem as rate-limiter gate 4
Multi-regionWhere does conversation state live?

D6. Surrounding Systems

ConceptThe question
Conversation storageAppend-only, sharded by conversation, hot/cold tiering
Retrieval augmentationYour home turf — embedding, ANN index, chunking, freshness
Safety/moderation in the pathIt costs latency; is it inline, parallel, or on the output stream?
Tool-calling loopsOne user turn becomes N model calls — the cost story changes completely
Evaluation and telemetryOffline evals, online metrics, and why token-level logging is expensive
Abuse detectionRate limits, cost caps, prompt-injection monitoring

Numbers to Quote Cold

Every one verified and attributed. Prices are volatile — always attach a date.

Hardware

GPUMemoryBandwidthDense compute
H100 SXM80 GB HBM33.35 TB/s989.5 TFLOP/s BF16 · 1,979 FP8 — dense; datasheet doubles these for 2:4 sparsity, which inference never uses
H200 SXM141 GB HBM3e4.8 TB/sidentical to H100
B200192 GB HBM3e~8 TB/sup to ~9,000 TFLOP/s FP4

The H100→H200 comparison is your evidence sentence: same compute, 43% more bandwidth, materially faster decode. That is the proof decode is bandwidth-bound.

Cost anchors (2026-reported, order of magnitude only)

GPUCloud hourly
H100~$1.50–3.00/hr
H200~$3.80/hr
B200~$6.50/hr

Derived rules

RuleValue
Model weights~2 bytes/param at FP16 → 70B ≈ 140 GB
KV cache per token2 × layers × kv_heads × head_dim × bytes
Decode step floorweight_bytes / bandwidth
Prefill FLOPs≈ 2 × params × prompt_tokens
Decode FLOPs per token≈ 2 × params

Run python3 gpu_math.py for all of these against a model you name.


The Eight Worked Designs

Track C has twelve worked designs; this track has eight of its own, in the same shape — nine sections, six hostile critiques, six revisions each. They are where the concept inventory above becomes a design round.

#DesignThe calculation that decides it
m01Multi-tenant LLM API platformone 128k request = 23% of a 4×H100 replica → fairness is KV·seconds, not requests
m02KV / prefix cache tierbreak-even 9.3 GB/s → NVMe is slower than recomputing
m03GPU cluster schedulerat 50% free, 0.5 expected fully-free nodes → fragmentation, not capacity
m04Pretraining data pipelineall-pairs dedup = 3.5M core-years → MinHash + LSH
m05Evaluation harness500 items resolves only > 6.7 pp → most reported gains are noise
m06Retrieval-augmented servingretrieval 85 ms, prefilling it 207 ms → optimize k, not the index
m07Multi-adapter (LoRA) serving+6% vs +151% by adapter shape → constrain it at registration
m08Training fault tolerancerestart is 5.4% of the run, invariant in the checkpoint interval

Attempt each before reading it. The index also carries what generalizes: which Track C primitives transfer, which distributed-systems instincts actively fail here, and the defect taxonomy across all 48 critiques.


The Calculator

cd tracks/ml-infra
python3 gpu_math.py --model llama-70b --gpu h100
python3 gpu_math.py --model llama-70b --gpu h100 --seq-len 8192 --batch 64
python3 gpu_math.py --list

It prints the memory budget, the maximum batch that fits, the decode-step floor, the roofline verdict, and the cost per million tokens. The output is the script for what you say out loud in the round — derive, do not recite.


Drill Set

DrillCadenceTrains
Design ChatGPT, altitude 1WeeklyThe default answer. 45 min, abstracted engine, traffic and coordination
Design ChatGPT, altitude 2WeeklyThe "open it up" answer. Same clock, engine internals
Altitude switch, mid-roundWeeklyI interrupt at minute 20 with "open up the serving layer." Trains the transition
Memory math from memoryDaily, 5 minA model and a GPU, no calculator. Weights, KV, max batch, decode floor
Technique tradeoff, 60sDailyPick one technique; state what it buys, costs, and when it loses
Autoscaling signal defenceWeekly"Why not just scale on GPU utilization?" Answer in 90 seconds with numbers
Paper read + one questionWeeklyRead one paper from the references; write the one question you would ask its authors
Benchmark a claimBiweeklyTake a claimed number, measure it, log the delta. Feeds "numbers I measured"

Failure Modes

FailureSymptomFix
Wrong altitude20 minutes on PagedAttention when they asked about trafficAltitude-1 default; say the abstraction sentence out loud
Can't open up on request"Open the serving layer" → hesitationAltitude-2 drill
Compute-bound reasoningSizing decode by FLOPsDerive the bandwidth floor every day until it is automatic
QPS autoscalingProposes an HPA on request countThe D4 table
Framework name-dropping"We'd use vLLM" with no mechanismFor every named system, state the mechanism and the tradeoff
Claiming internal knowledge"OpenAI does X internally"Say what is public and what you are inferring. Nothing about their stack is public at that detail
Unattributed numbers"vLLM gets 3–5x"Either measure it or attribute it. Both are fine; asserting is not
Ignoring costA design with no $/tokenIt is the business. Say the number
Forgetting the KV cacheSizes memory by weights onlyIt is the constraint, not the weights

Self-Assessment Rubric

LevelStandard
L0Cannot size a model's memory; treats the GPU as a black box
L1Knows the vocabulary; recites techniques without tradeoffs; would scale on QPS
L2Derives the memory budget and decode floor; names correct autoscaling signals; holds altitude 1 and can open to altitude 2
L3Above, plus frames techniques as points on a throughput/latency curve, reasons about per-tenant fairness and cost per token unprompted, and states clearly what is public versus inferred

Hire-bar translation

VerdictWhat it looks like
No hireDesigns it like a stateless web service
Hire (senior)Correct architecture; abstracts the engine; some memory math
Strong hire (senior)Above, plus correct autoscaling signals with the reason QPS fails
Hire (staff)Above, plus the throughput/latency curve framing and traffic-class separation
Strong hire (staff)Above, plus a cost model, a fairness policy, and an explicitly accepted failure mode

References

Serving systems and papers

Implementations to read

Operational grounding