Skip to content

ML system design (LLM era)

How to answer a 45–60 minute ML system design round, with eight worked designs: LLM serving, enterprise RAG, a pretraining run, a pretraining data pipeline, RL post-training infrastructure, an agent platform, an eval platform and a classic recommender. Each design gives explicit numbers, a diagram, trade-offs, failure modes and what separates a strong answer from a weak one. Outline each design yourself before reading it.

Contents

The framework

Step Time What you do What the interviewer is checking
1. Clarify 5 min Users, task, quality bar, latency SLOs, scale (peak and average), privacy and compliance, budget, what exists today You design for the actual problem, not a generic one
2. Napkin math 5 min QPS, tokens in and out, FLOPs, memory (weights, KV, activations), GPUs, $ per request. Say the numbers out loud You can size a system; most candidates are weakest here
3. Architecture 10 min Draw the data path end to end, then the control plane (deploys, scaling, monitoring) Clean decomposition, clear interfaces
4. Model and data choices 10 min API vs open weights vs fine-tuned; size vs latency; quantization; routing; where training data comes from Choices justified by the numbers and the quality bar
5. Evaluation 5–10 min Offline eval sets, online metrics, guardrails, a regression gate before every deploy You know how you would know it works
6. Failure modes and scaling 5–10 min Bursts, long-tail inputs, cache misses, hardware failures, provider outages, abuse, drift, cost blowups Operational maturity
7. Iterate 2–5 min What you build first, what you measure, what you defer Judgment and prioritization

Tip

Spend the first minute agreeing on two or three numbers (peak QPS, input and output length, latency target). Every later decision should trace back to them. If the interviewer does not give numbers, propose reasonable ones and say "I'll assume X; tell me if that's off".

Tip

Draw the diagram early and keep pointing at it. When the interviewer pushes on a component, zoom into that box rather than redrawing everything.

One-page answer template

Copy this into a notes file before a mock and fill it in as you talk. If a line stays empty at minute 40, that is the gap the interviewer noticed too.

PROBLEM         one sentence, in the user's terms
USERS / SLOs    who; p50/p95 latency (TTFT, ITL, end to end); availability; quality bar
SCALE           peak QPS ___  avg QPS ___  input tokens ___  output tokens ___  corpus/data size ___
NUMBERS         FLOPs/request ___  weights ___ GB  KV/token ___ KiB  GPUs ___  $/request ___
                bottleneck: compute | memory bandwidth | memory capacity | network | human labels
ARCHITECTURE    data path: ___ -> ___ -> ___ -> ___
                control plane: deploys, autoscaling, config, secrets
MODEL           choice + why; size; precision; fine-tuning?; fallback model
DATA            sources; labels; freshness; privacy/ACLs; retention
EVAL            offline set (size, CI width); online metrics; guardrails; release gate
FAILURE MODES   top 5, each with detection + mitigation
TRADE-OFFS      2-3 explicit "I chose X over Y because Z; I'd revisit if W"
V1 / LATER      build first ___  measure first ___  defer ___

Reference numbers

Use these for estimates and say they are approximate; verify spec sheets before quoting precise figures.

Quantity Value
H100 SXM dense throughput ≈ 989 TFLOP/s bf16, ≈ 1,979 TFLOP/s FP8
H100 memory 80 GB HBM3, ≈ 3.35 TB/s
Interconnect NVLink ≈ 900 GB/s bidirectional per GPU; InfiniBand NDR ≈ 50 GB/s per port; PCIe 5.0 x16 ≈ 64 GB/s per direction
Training FLOPs ≈ 6N per token (2N forward, 4N backward)
Inference FLOPs ≈ 2N per token, plus attention 2·n_layers·T·d per token
Training memory ≈ 16 bytes/param with mixed-precision Adam, plus activations
KV cache per token 2 · n_layers · n_kv_heads · d_head · bytes (Llama-2-70B shape: 320 KiB in bf16, 160 KiB in FP8)
Decode time per step ≈ (weight bytes + KV bytes read) / bandwidth, when memory-bound
Realistic efficiency 35–50% MFU for large dense training; 60–80% of peak bandwidth for decode

The derivations are in lab 03 and module 02; the question bank has drills.


A. LLM serving platform

Prompt. Serve a 70B dense chat model at 1,000 requests/s peak, averaging 1,000 input and 300 output tokens, with p95 time to first token (TTFT) under 1 s and p95 inter-token latency (ITL) under 50 ms.

Clarify. Peak vs average traffic (diurnal ratio decides autoscaling savings); prompt-length distribution and maximum context; how much of each prompt is a shared system prompt; whether FP8 quality is acceptable; streaming; regions; a latency tier vs a batch tier.

Numbers

Quantity Calculation Result
Input tokens/s 1,000 × 1,000 1.0M
Output tokens/s 1,000 × 300 300k
Prefill compute 2 × 70·10⁹ × 10⁶ tokens/s 1.4·10¹⁷ FLOP/s
Weights in FP8 70·10⁹ × 1 byte 70 GB: TP = 4 on 80 GB GPUs leaves ≈ 250 GB per replica for KV and activations
KV per token (FP8 KV, 80 layers, 8 KV heads, d_head 128) 2 × 80 × 8 × 128 × 1 B 160 KiB
Prefill cost per request 1.4·10¹⁴ FLOPs / (1,979·10¹² × 0.4 assumed MFU) ≈ 0.18 GPU-s
Decode step, TP = 4, batch 128, ≈ 1,150-token average context per GPU: 17.5 GB weights + 128 × 1,150 × 160 KiB / 4 ≈ 6 GB of KV; 23.5 GB / (0.7 × 3.35 TB/s) ≈ 10 ms, plus ≈ 1.6 ms of TP all-reduce latency (160 small all-reduces) ≈ 12 ms per step: ITL ≈ 12 ms, ≈ 10.7k tokens/s per replica
Decode cost per request 300 tokens × 4 GPUs × 12 ms / 128 ≈ 0.11 GPU-s
GPUs busy at peak (0.18 + 0.11) × 1,000 ≈ 290
GPUs provisioned (≈ 65% target utilization for p95 headroom) 290 / 0.65 ≈ 450 GPUs, ≈ 112 TP = 4 replicas
TTFT from compute alone 1.4·10¹⁴ / (4 × 792·10¹²) ≈ 45 ms, so queueing dominates TTFT
Cost at an assumed $2 per GPU-hour 450 × $2 per hour / (1.08·10⁹ output tokens per hour) ≈ $0.83 per million output tokens at peak load

Two conclusions fall out of the numbers. First, prefill is about 60% of GPU time at this input/output ratio, so the biggest cost levers are prefix caching and shorter prompts: if 600 of the 1,000 input tokens are a cached system prompt, prefill cost drops to ≈ 0.07 GPU-s and the fleet shrinks by ≈ 38%. Second, a 1,000-token prefill takes ≈ 45 ms on a replica, so inserting it between decode steps would push ITL from 12 ms to ≈ 57 ms and break the SLO; prefill must be chunked or moved to separate GPUs.

Architecture

flowchart LR
    C[Clients] --> G["API gateway<br/>auth, quotas, rate limits"]
    G --> R["Router<br/>prefix-cache aware, SLO aware"]
    R --> Q[("Per-tier queues")]
    Q --> P1["Replica 1: 70B FP8, TP=4<br/>continuous batching<br/>chunked prefill, paged KV"]
    Q --> P2["Replica 2 ... N"]
    P1 --> S["Token stream to client"]
    P2 --> S
    P1 --> M["Metrics: TTFT, ITL,<br/>queue depth, KV usage"]
    M --> A["Autoscaler"]
    A --> P2
    REG["Model registry<br/>+ eval gate"] --> P1
  • Engine: continuous batching with paged KV (vLLM, SGLang or TensorRT-LLM class), chunked prefill with chunks of ≈ 256–512 tokens. A 256-token chunk adds ≈ 11 ms of compute per GPU to a step that is otherwise memory-bound, so ITL rises to roughly 15 ms instead of spiking by 45 ms.
  • Router: send requests with the same prefix to the replica that holds it (cache locality), but cap per-replica load so a popular prefix cannot overload one replica. Admission control per tier: reject early with retry-after when the queue predicts a TTFT violation, rather than accepting and missing the SLO.
  • Batch size from the SLO: raise batch size until p95 ITL approaches the target minus headroom; that sets throughput per GPU and therefore cost.
  • Autoscaling on queue depth and KV-cache utilization, not CPU. Loading 70 GB of weights takes tens of seconds to minutes, so keep warm spare capacity for bursts.
  • Deploys: canary new weights or engine versions on a small traffic slice, with an automatic eval gate (quality suite with paired comparison against production) and latency checks.

Trade-offs

Decision Option chosen Alternative When to switch
Precision FP8 weights and KV bf16 FP8 fails the paired quality eval on a slice you care about (e.g. a language or long context)
Parallelism TP = 4 per replica TP = 8 A premium low-latency tier: per-token weight time halves, but communication does not, and cost per token rises
Prefill placement Chunked prefill on shared GPUs Disaggregated prefill and decode pools Very large scale or strict SLOs on both TTFT and ITL; needs ≈ 150 GiB/s of cluster-wide KV transfer here (10⁶ tokens/s × 160 KiB)
Speculative decoding Latency tier only Everywhere At batch 128 decode is closer to compute-bound per replica and verification costs real FLOPs; at small batch it cuts ITL substantially

Failure modes

Failure Detection Mitigation
Traffic burst Queue depth, predicted TTFT Admission control, shed the batch tier first, warm spares
Very long prompts (50k+ tokens) Prompt-length histogram Separate long-context pool; charge by tokens; cap context per tier
KV cache exhausted KV utilization near 100%, preemptions Preempt and swap to host memory or recompute; lower max batch; FP8 KV
Hot prefix overloads one replica Per-replica load skew Replicate the prefix to several replicas; bounded-load consistent hashing
GPU or node failure Health checks, NCCL timeouts Drain and replace the replica; retry in-flight requests elsewhere
Bad model or engine release Canary evals, error rates Automatic rollback; shadow traffic before canary

What a strong candidate says that a weak one does not

  • Weak: "Put it on vLLM behind a load balancer and autoscale." Strong: computes that prefill dominates GPU time at a 1,000/300 token ratio and names prefix caching as the first cost lever.
  • Explains why chunked prefill (or disaggregation) is required to meet the ITL SLO, with the 45 ms number.
  • Derives batch size from the ITL target, and cost per token from batch size.
  • Knows TTFT at this prompt length is mostly queueing, so admission control matters more than faster prefill kernels.
  • Treats quantization as a quality decision that needs a paired eval, not a free speedup.

B. Enterprise RAG with access control and citations

Prompt. Build question answering over 10M internal documents for 500 enterprise tenants, with citations, respecting each source system's permissions. 50 queries/s at peak; p95 time to first token under 2.5 s.

Clarify. Document types (PDFs with tables, scans, slides, wiki pages, tickets); how fast permission changes and deletions must propagate; languages; whether answers may combine documents the user can see with ones they cannot (never); data residency; how "correct" is judged.

Numbers

Quantity Calculation Result
Corpus size 10M docs × ≈ 2,000 tokens ≈ 20B tokens
Chunks 500-token chunks with ≈ 10% overlap ≈ 44M
Vector storage, 1,024 dims 44M × 4 KiB (fp32) / 2 KiB (fp16) / 1 KiB (int8) ≈ 168 GiB / 84 GiB / 42 GiB, plus graph overhead for HNSW
Initial embedding compute, ≈ 335M-parameter encoder 2 × 335·10⁶ × 20·10⁹ = 1.3·10¹⁹ FLOPs at ≈ 300 TFLOP/s effective ≈ 12 H100-hours: re-embedding the corpus is cheap
Reranking, 100 candidates × ≈ 600 tokens, ≈ 300M-parameter cross-encoder 2 × 300·10⁶ × 60,000 = 3.6·10¹³ FLOPs per query ≈ 0.1 s on one GPU; at 50 QPS ≈ 6 GPUs busy, so rerank 50 candidates or use a smaller model if that is too costly
Generation context 8 chunks × 500 tokens + instructions ≈ 5k input tokens, ≈ 400 output

The numbers say that embedding compute is not the constraint. Parsing quality, permission sync and evaluation are where the engineering effort goes.

Architecture

flowchart LR
    subgraph ING["Ingestion (continuous)"]
        SRC["Connectors: SharePoint,<br/>Drive, Confluence, tickets"] --> PAR["Parse: layout, tables, OCR"]
        PAR --> CH["Chunk + contextual header<br/>(title, section path)"]
        CH --> EMB["Embed"]
        CH --> BM["BM25 index"]
        EMB --> VEC[("Vector index,<br/>partitioned by tenant")]
        SRC --> ACL["ACL + deletion sync"]
        ACL --> VEC
        ACL --> BM
    end
    subgraph QRY["Query path"]
        U["User + identity"] --> RW["Query rewrite"]
        RW --> HY["Hybrid retrieval<br/>ACL filter enforced"]
        HY --> RR["Cross-encoder rerank"]
        RR --> GEN["Generate with citations"]
        GEN --> CC["Citation check"]
        CC --> ANS["Answer + sources"]
    end
    VEC --> HY
    BM --> HY
  • Parsing: layout-aware extraction keeps tables and headings; OCR for scans; each chunk gets a header with document title and section path so it makes sense out of context.
  • Retrieval: BM25 plus dense retrieval fused with reciprocal rank fusion; BM25 catches product codes and names that embeddings blur. Retrieve ≈ 100, rerank to ≈ 8.
  • Permissions: store allowed principals (users and groups) on every chunk; resolve the user's groups from the identity provider at query time and apply the filter inside retrieval, never after generation. Large tenants get their own index partitions; small tenants share an index with a mandatory tenant filter. Heavily filtered approximate-nearest-neighbor search can lose recall, which is another reason to partition.
  • Citations: the generator must cite chunk ids for each claim. A post-check verifies that every cited id was in the retrieved set and that the cited text supports the claim (a small entailment model or validated judge); unsupported claims are removed or flagged. Say "I could not find this" when retrieval returns nothing relevant.
  • Freshness and deletion: incremental ingestion from change feeds; deletions and permission revocations propagate within a stated SLA (for example minutes), with tombstones checked at query time until the index is compacted.

Trade-offs

Decision Options Guidance
Index topology Per-tenant index vs shared with filter Per-tenant for large tenants and strict isolation; shared for the long tail
Chunk size 200–1,000 tokens Smaller improves precision, larger keeps context; tune on the eval set, and add neighbor expansion at read time
Reranker None / cross-encoder / LLM reranker Cross-encoder is the usual sweet spot; measure the recall gain against the latency
Long context instead of RAG Put whole documents in context Good for a few long documents per query; does not replace permission filtering or corpus-scale search

Failure modes

Failure Detection Mitigation
Permission leak (most serious) Canary documents with restricted ACLs queried by test users; audits Filter in retrieval, not in the prompt; sync SLA with alerts; deny on unknown ACL
Stale deleted documents answering questions Deletion canaries Tombstone check at query time
Table or scan parsed into garbage Parse-quality sampling per file type Better parsers, OCR, route failures to a review queue
Answer split across chunk boundaries Error analysis on failed queries Overlap, neighbor expansion, section-aware chunking
Prompt injection inside documents Red-team documents Treat retrieved text as data; no tool access from this path; output filtering
Hallucinated or wrong citations Citation checker failure rate Enforce the citation contract; drop unsupported claims
Embedding model upgrade Planned Dual-write a new index, compare on evals, then switch

Evaluation

  • Offline, per tenant where possible: 200+ real questions with labeled relevant passages. Retrieval recall@20 and nDCG@10; answer correctness; faithfulness (claims supported by cited text); citation precision; correct refusal when the answer is absent.
  • Online: citation click-through, thumbs up/down with reasons, escalations to humans, "no answer" rate.
  • A regression gate on any change to parser, chunker, embedder, reranker or prompt, with paired comparisons on the same questions.

What a strong candidate says that a weak one does not

  • Weak: "Chunk, embed, put it in a vector database, call the LLM." Strong: starts with permissions and deletion as correctness requirements, and enforces them inside retrieval.
  • Calculates that embedding is cheap (≈ 12 GPU-hours) and spends the design time on parsing, ACLs and evals instead.
  • Evaluates retrieval and generation separately, so a failure can be attributed to one stage.
  • Uses hybrid retrieval for identifiers and names, and explains why.
  • Has an explicit plan for prompt injection in retrieved content.

C. Pretraining run: 7B on 2T tokens

Prompt. Plan the pretraining of a 7B dense model on 2T tokens using 256 H100s (32 nodes of 8). The detailed paper exercise is in module 05 §8.

Clarify. Target capabilities (English only, multilingual, code), context length, deadline, whether a tokenizer and data pipeline exist (see design D), and what evaluation defines success.

Numbers

Quantity Calculation Result
Training compute 6 × 7·10⁹ × 2·10¹² 8.4·10²² FLOPs
Cluster throughput at 40% MFU 256 × 989·10¹² × 0.4 1.01·10¹⁷ FLOP/s
Pure training time 8.4·10²² / 1.01·10¹⁷ 8.3·10⁵ s ≈ 9.6 days; plan ≈ 11–12 days with restarts and evals
Global batch 1,024 sequences × 4,096 tokens ≈ 4M tokens (Llama 2 used 4M) → 500k steps, ≈ 1.7 s per step
Tokens per GPU per step 4M / 256 16,384 = 4 sequences: micro-batch 1 with 4 accumulation steps, or 2 × 2
Model states 16 bytes × 7·10⁹ 112 GB total
States per GPU with HSDP (shard within node, replicate across 32 nodes) 112 GB / 8 14 GB
Activations, micro-batch 1 × 4,096, FlashAttention 34 · s · h bytes per layer × 32 layers ≈ 18 GB; fits beside 14 GB of states, with room for micro-batch 2 or selective recomputation
Cross-node gradient all-reduce per step each GPU all-reduces its 1/8 shard: 1.75 GB bf16 → ≈ 3.5 GB sent at ≈ 50 GB/s ≈ 70 ms per 1.7 s step, easily overlapped with backward
Expected interruptions Llama 3 reported 419 unexpected interruptions in 54 days on 16,384 GPUs ≈ 4.7·10⁻⁴ per GPU-day; × 256 GPUs ≈ 0.12 per day: expect 1–2 during the run
Checkpoint interval (Young) √(2 × C × MTBF) with C ≈ 30 s blocking and MTBF ≈ 8 days ≈ 1.8 h; checkpoint roughly hourly anyway, because loss-spike rewinds also need recent checkpoints

Architecture

flowchart LR
    D[("Tokenized shards<br/>+ manifest")] --> L["Deterministic loader<br/>resumable position, per-rank seeds"]
    L --> T["Trainer: 32 nodes × 8 H100<br/>HSDP: shard in node,<br/>replicate across nodes"]
    T --> CK[("Async sharded checkpoints<br/>hourly + daily permanent")]
    CK --> EV["Eval workers<br/>(separate GPUs)"]
    T --> MON["Metrics: loss per domain, grad norm,<br/>max logits, MFU per rank"]
    MON --> AL["Alerts + spike playbook"]
    AL -.->|"rewind, skip batch"| CK
    EV --> DASH["Dashboard with CIs"]

Recipe to start from (then ablate): Llama-style architecture (RMSNorm pre-norm, SwiGLU, RoPE, GQA), AdamW with β = (0.9, 0.95), weight decay 0.1, gradient clipping at 1.0, warmup ≈ 2,000 steps, peak LR ≈ 3·10⁻⁴ with cosine or WSD decay; these match what Llama 2 7B reported. Add QK-norm or z-loss if you see logit growth in proxies.

Before the big run: spend ≈ 5–10% of the budget on proxy runs (≤ 1B parameters) to choose the LR, data mixture and any architecture change, and run a short full-scale job (a few hours) to measure real MFU, memory and checkpoint times.

During the run: held-out loss per data domain every ~1,000 steps; a downstream suite on checkpoints every ~50–100B tokens with CIs (small-model benchmarks are noisy, so compare trends, not single points); a straggler detector comparing per-rank step times.

Trade-offs

Decision Choice Alternative and why
Sharding HSDP (shard within node) Full FSDP over 256 GPUs saves memory but puts all-gathers on InfiniBand every layer; TP is unnecessary at 7B
Sequence length 4k for most tokens, a long-context phase at the end Training at 32k throughout multiplies attention cost for little benefit early
Precision bf16 with fp32 master weights FP8 training raises throughput but adds scaling complexity and risk; adopt only after proxy runs show parity
Schedule WSD Cosine is standard; WSD lets you branch cooldowns at several token counts and extend the run

Failure modes

Failure Signal Response
Loss spike Grad norm and max logit jump Rewind to the last good checkpoint, skip the batch, lower LR if it recurs
Straggler GPU One rank's step time is high Replace the node; stragglers slow the whole job
Silent data corruption (hardware computing wrong values) Loss or grad-norm anomalies without a data cause; mismatched replicas Periodic cross-replica checksums, known-answer tests, retire bad hosts
Data loader bug (repeated or skipped shards) Per-shard token accounting Deterministic manifest, assert every shard is consumed once per epoch
Checkpoint write throttled or corrupt Save time, restore tests Async writes, verify by restoring periodically

What a strong candidate says that a weak one does not

  • Gives the 9.6-day number in a minute, then adds overheads for failures and evals.
  • Chooses a parallelism layout from memory and communication numbers, not from habit.
  • Plans ablations and a short full-scale shakedown before committing the budget.
  • Has a written loss-spike playbook and knows that deterministic data resumption is part of fault tolerance.
  • Mentions silent data corruption and straggler detection, which dominate operations at scale.

D. Pretraining data pipeline

Prompt. Build the pipeline that produces the 2T training tokens for design C: filtered, deduplicated English web text plus code and multilingual data including Indian languages, and a way to test whether any pipeline change helps.

Clarify. Token target per source; languages; licensing and opt-out policy; PII policy; which evals the data must not contain; compute budget for processing; how often the pipeline reruns.

Numbers

Quantity Calculation Result
Yield per Common Crawl snapshot FineWeb produced ≈ 15T tokens from 96 snapshots ≈ 156B tokens per snapshot after filtering and dedup
Snapshots for ≈ 1.6T English web tokens (80% of 2T) at similar filtering 1.6T / 156B ≈ 10–11 snapshots
With an aggressive educational-quality filter FineWeb-Edu kept ≈ 1.3T of ≈ 15T tokens (≈ 9%) All ≈ 100 snapshots give only ≈ 1.3T: trade quality for quantity, or repeat data (≈ 4 epochs costs little, per Muennighoff et al., 2023)
Pages per snapshot order of 2–3 billion (check the crawl's release notes)
HTML-to-text extraction cost if ≈ 10 ms per page per core (measure on a sample): 2.5·10⁹ × 10 ms ≈ 7,000 core-hours per snapshot; ≈ 3 days on 1,000 cores for 10 snapshots
MinHash dedup signatures 14 bands × 8 rows = 112 hashes; threshold ≈ (1/14)^(1/8) ≈ 0.72; one 8-byte key per band 112 bytes per document ≈ 280 GB per 2.5B documents: a distributed group-by, then union-find over candidate pairs
Model-based quality classifier, ≈ 100M-parameter encoder on ≈ 150B tokens 2 × 10⁸ × 1.5·10¹¹ = 3·10¹⁹ FLOPs at ≈ 100 TFLOP/s effective ≈ 80 GPU-hours per snapshot (less if you score only the first 512 tokens per document)
Tokenized storage, 128k vocabulary 2·10¹² tokens × 4 bytes (uint32; uint16 only fits vocabularies below 65,536) ≈ 8 TB

Architecture

flowchart LR
    CC["Common Crawl WARC"] --> EX["HTML to text<br/>extraction"]
    EX --> LID["Language ID"]
    LID --> URL["URL and domain filters<br/>opt-outs, blocklists"]
    URL --> HEU["Heuristic filters<br/>length, repetition, symbols"]
    HEU --> DD["MinHash dedup<br/>per snapshot"]
    DD --> QC["Quality classifier"]
    QC --> PII["PII redaction"]
    CODE["Code: license filter,<br/>dedup, secrets scan"] --> DC
    IND["Multilingual and Indic<br/>sources"] --> LID
    PII --> DC["Decontamination<br/>vs eval sets"]
    DC --> TOK["Tokenize, shard,<br/>write manifest"]
    TOK --> MIX["Mixture sampler"]
    MIX --> PX["Proxy-model ablation<br/>fixed eval suite + CIs"]
    PX -.->|"accept or reject change"| HEU
  • Every document keeps provenance: source URL, snapshot, which filters it passed with which scores, and content hashes. Datasets are immutable, versioned manifests, so any training run can name exactly what it saw.
  • The funnel is a first-class output: documents and tokens in and out of every stage, broken down by language and domain, plus a viewer to read random kept and removed samples. Most pipeline bugs are found by reading samples.
  • Changes are tested, not argued: a pipeline change is accepted only if proxy models (≈ 1B parameters, tens of billions of tokens, several seeds or a bootstrap over eval items) trained on the new data beat the old data on a fixed, decontaminated eval suite at matched tokens.
  • Dedup scope matters: FineWeb reported that deduplicating each snapshot separately worked better than one global dedup across all snapshots. Test the choice on proxies rather than assuming more dedup is always better.
  • Indian languages need their own handling: language ID confuses related languages and romanized text; an English-trained quality classifier can reject good Telugu text, so train or validate classifiers per language with native-speaker review; volumes are small, so upsample within the ≈ 4-epoch budget; check tokenizer fertility (see lab 04).
  • Code: permissive-license filtering, exact and near dedup, removal of generated and minified files, secret and PII scanning, and repository-aware ordering so related files appear together.

Trade-offs

Decision Options Consideration
Filtering strength Light vs aggressive Aggressive filtering improves knowledge benchmarks per token but shrinks and narrows the data (classifiers favor one style)
Dedup granularity Document vs paragraph or line Line-level removes boilerplate (menus, cookie notices) but can break documents
Classifier type fastText vs small transformer fastText costs almost nothing on CPU; transformers judge quality better but need GPUs
Synthetic data None vs rephrased or generated Adds targeted skills and diversity of format; risks homogeneity and generator errors; test on proxies

Failure modes

Failure Detection Mitigation
Extraction drops code blocks, math or tables Sample review by content type Extraction settings per page type; targeted parsers
Filters remove dialects or languages disproportionately Funnel by language and region Per-language thresholds, audits
Benchmark contamination n-gram overlap scans against eval sets Decontaminate before tokenizing; keep a list of protected evals
License or opt-out violations Provenance audits Filter at ingest, keep provenance for removal requests
PII in training data Scanners, sampled audits Redaction; exclude high-risk sources
Pipeline non-determinism makes ablations irreproducible Hash comparison of reruns Seeded, versioned stages; manifests

What a strong candidate says that a weak one does not

  • Weak: lists the stages. Strong: describes how each stage is validated with proxy models and a fixed eval suite, and treats the funnel as a monitored product.
  • Sizes the job: snapshots needed for the token target, and where the compute goes (extraction, not dedup).
  • Knows the quantity–quality trade-off in numbers (FineWeb vs FineWeb-Edu) and how repetition changes it.
  • Builds decontamination, provenance and opt-out handling in from the start.
  • Treats non-English data as needing its own classifiers and review, not a translation of the English pipeline.

E. RL post-training infrastructure

Prompt. Build infrastructure to train an 8B model with GRPO on coding problems verified by unit tests. Each step uses 512 prompts × 8 samples; responses can be up to 16k tokens.

Clarify. Model size and reference model; synchronous or asynchronous updates; problem sources and test quality; languages to execute; security requirements for running model-written code; target steps and wall-clock.

Numbers

Quantity Calculation Result
Rollouts per step 512 × 8 4,096
Generated tokens per step 4,096 × ≈ 2,000 average ≈ 8.2M
Rollout throughput per GPU (8B bf16, batch 256, ≈ 1.5k average context, 128 KiB KV per token) per step: 16 GB weights + 256 × 1,500 × 128 KiB ≈ 50 GB of KV → ≈ 29 ms at 70% of 3.35 TB/s → ≈ 9k tokens/s; assume ≈ 5k after overheads (measure)
Rollout GPU time 8.2M / 5k ≈ 1,640 GPU-s: ≈ 26 s on 64 GPUs, if perfectly balanced
The tail A sequence decodes at ≈ 35 tokens/s inside a batch of 256 and ≈ 150–200 tokens/s once alone A 16k-token response takes roughly 1.5–8 minutes while the average finishes in 26 s
Trainer compute ≈ 10M tokens (responses + prompts): policy 6N + reference forward 2N + old-policy log-probs 2N = 10N per token → 10 × 8·10⁹ × 10⁷ 8·10¹⁷ FLOPs ≈ 2,000 GPU-s at 400 TFLOP/s: ≈ 42 s on 48 GPUs
Sandbox executions 4,096 per step, median ≈ 2 s CPU, 10 s timeout ≈ 8,000–40,000 CPU-s per step: ≈ 8–40 s on 1,000 cores; overlap with generation
Weight sync 16 GB bf16 per update to 64 rollout GPUs ≈ 1–2 s with a pipelined broadcast over InfiniBand

The tail row is the key insight: in a synchronous design, step time is set by the longest response, not the average, and GPUs idle while the last sequences finish.

Architecture

flowchart LR
    PS["Prompt sampler<br/>curriculum, pass-rate filter"] --> RO["Rollout fleet<br/>inference engine, ≈ 64 GPUs"]
    RO --> SB["Sandbox pool<br/>microVMs, no network,<br/>CPU, memory and time limits"]
    SB --> RW["Rewards + group<br/>advantages"]
    RW --> BUF[("Rollout buffer<br/>staleness ≤ 1 step")]
    BUF --> TR["Trainer: FSDP, ≈ 48 GPUs<br/>recompute log-probs"]
    TR -->|"weights + version tag"| RO
    TR --> CK[("Checkpoints")]
    CK --> EV["Held-out evals<br/>+ reward-hacking audits"]
    RW --> MON["Monitoring: reward, length, entropy,<br/>KL, clip fraction, zero-advantage groups,<br/>sandbox timeouts"]
  • Asynchronous rollouts: the trainer consumes completed groups while generation continues, with staleness bounded (for example one policy version) and corrected by the clipped importance ratio. Partial rollouts (pause long generations and resume them with new weights) cut the tail further.
  • Do not simply take the first groups to finish: that biases training toward short responses. If you over-sample prompts, keep selection independent of length or correct for it.
  • Log-probabilities: recompute the old-policy log-probabilities with the trainer; the inference engine's numerics differ, and treating them as identical silently makes the data off-policy. Track the engine–trainer KL as a metric.
  • Sandbox: a fresh microVM or gVisor container per execution, no network, read-only test files, resource limits, deterministic seeds and no wall-clock dependence. Rerun reference solutions to find flaky tests before they become reward noise.
  • Prompt curriculum: drop problems the model always solves or never solves (zero advantage, no gradient) and refresh the pool as the model improves.
  • Version every rollout with the weight version used; a silent failure of weight sync (rollouts on stale weights) otherwise looks like slow learning.

Trade-offs

Decision Options Consideration
Sync vs async Synchronous is simplest and exactly on-policy Async raises throughput 2× or more when lengths vary widely; needs staleness control
Colocated vs separate pools Same GPUs alternate generation and training Colocation avoids idle pools at small scale; separate pools scale and pipeline better
Group size G 4–16 Larger G gives better baselines and fewer zero-advantage groups at higher rollout cost
KL penalty k3 KL to reference vs none Without KL you skip the reference forward (≈ 20% of trainer compute here) and allow larger moves; with a learned reward model keep it
Max length 8k–32k Longer allows harder reasoning but worsens the tail; use overlong shaping rather than hard truncation rewards

Failure modes

Failure Signal Mitigation
Reward hacking (special-casing tests, editing tests, early exit) Reward rises, held-out pass rate flat; audits of top-reward samples Hidden tests, immutable test files, strict harness, penalties, audits
Flaky tests Reference solutions fail intermittently Quarantine flaky problems; multiple runs
Entropy collapse Entropy drops, pass@k stops improving Clip-higher, temperature, filtering zero-advantage groups
Length explosion Mean length climbs without accuracy gains Token-level loss normalization, overlong penalties, length monitoring
Sandbox escape or abuse Security monitoring Defense in depth: microVM, no network, least privilege, separate accounts
Stale weights on rollouts Version-tag mismatch Assert versions, checksums after sync

What a strong candidate says that a weak one does not

  • Identifies rollout generation, and specifically the length tail, as the throughput bottleneck, with numbers.
  • Sizes rollout, trainer and sandbox pools so their times match, and overlaps them.
  • Knows the log-probability mismatch between inference engine and trainer, and the length bias of first-finished selection.
  • Treats the sandbox as a security boundary and a source of reward noise.
  • Monitors the specific GRPO failure signals (entropy, length, zero-advantage fraction, clip fraction), not only mean reward.

F. Agent platform with tool sandboxing and evals

Prompt. Design a platform that runs customer-configured agents (coding, data analysis, internal workflows) on a frontier model: 10,000 concurrent sessions at peak, up to 50 steps each, with tools that run code, browse the web and call customer APIs. It must be safe, observable, and measurably improving.

Clarify. Which actions are irreversible (payments, emails, deploys, deletes); who approves them; customer data boundaries; whether the model is self-hosted or an API; session length and budgets; what "task success" means for each agent type.

Numbers

Quantity Calculation Result
Input tokens per session 50 steps with context growing from ≈ 5k to ≈ 60k: ≈ 32.5k average × 50 ≈ 1.6M, of which only ≈ 55k (≈ 1.1k per step) are new
Effect of prompt caching If cached input costs 10% of uncached (some APIs price cache reads this way): 55k + 0.1 × 1.6M ≈ 215k uncached-equivalent ≈ 7× cheaper input; without caching, agents at this length are rarely affordable
Output tokens per session 50 × ≈ 300 ≈ 15k
Model calls per second 10,000 sessions, one step per ≈ 10 s (model plus tool time) ≈ 1,000 calls/s: the same order as design A
Resident context 10,000 × 32.5k tokens × 160 KiB (70B-class, FP8 KV) ≈ 48 TiB: far more than GPU memory, so KV must be tiered to host memory or SSD, or recomputed
Reload vs recompute a 30k-token context reload 30k × 160 KiB ≈ 4.6 GiB at ≈ 25 GB/s ≈ 0.2 s; recompute 2 × 70·10⁹ × 3·10⁴ = 4.2·10¹⁵ FLOPs ≈ 1.3 s on a TP = 4 replica Offloading beats recompute by ≈ 6× while the agent waits on a tool
Sandboxes 10,000 × 2 vCPU, 2 GB RAM 20k vCPUs, 20 TB RAM if all active; most idle during model calls, so pause or snapshot them
Sandbox start Firecracker documents microVM launch in as little as ≈ 125 ms Per-session microVMs are practical
Eval precision 300 tasks, success near 50%: SE ≈ √(0.25/300) ≈ 2.9 points, so changes under ≈ 6 points need paired comparison on the same tasks

If the model is behind an API, the same physics shows up as cache pricing and cache lifetime: a tool call that outlasts the cache's time-to-live makes the next step pay full price.

Architecture

flowchart LR
    U["User or API"] --> OR["Session orchestrator<br/>durable step log, budgets"]
    OR <--> MG["Model gateway<br/>routing, prompt caching"]
    OR --> PE{"Policy engine<br/>allow / deny / ask human"}
    PE --> TRT["Tool runtime<br/>typed schemas, timeouts"]
    TRT --> SB["Per-session sandbox<br/>microVM, no ambient credentials"]
    SB --> EG["Egress proxy<br/>allow-list, logging"]
    SEC["Secrets broker<br/>short-lived scoped tokens"] --> EG
    EG --> EXT["Customer APIs, web"]
    TRT --> OS[("Output store<br/>large results as handles")]
    OR --> TRC[("Trajectory traces")]
    TRC --> EVS["Eval service<br/>task suites, pass^k,<br/>injection red team"]
    EVS -.->|"release gate"| MG
  • Orchestrator: each step (model call, tool call, result) is persisted before the next begins, so sessions survive crashes and can be replayed. Budgets on steps, tokens, wall-clock and money are enforced here, not left to the model.
  • Tools: typed JSON schemas with versions; validation of arguments before execution; idempotency keys so a retried call cannot, for example, pay twice; structured errors returned to the model so it can recover; large outputs stored as files and returned as a handle plus a summary, with a search tool to read more.
  • Policy engine: rules per tool and argument pattern (read-only actions allowed; writes to customer systems need a scope; irreversible or external actions such as sending email, deploying or deleting require human approval). The model never decides its own permissions.
  • Sandbox: one microVM (or gVisor container for lower-risk tools) per session, resource limits, filesystem snapshots for rollback, network only through an egress proxy with an allow-list.
  • Secrets: the broker attaches short-lived, narrowly scoped credentials at the proxy. Secrets never enter the model's context, so prompt injection cannot read them. Traces are scanned and redacted.
  • Prompt injection: content from web pages, files and tool outputs is untrusted data. The dangerous combination is private data plus untrusted content plus a way to send data out; the policy engine and egress allow-list break that chain for each task.
  • Context management: keep the stable prefix (system prompt, tool definitions) first and unchanged so caches hit; compact old tool outputs into summaries when context grows, accepting a cache miss at that point.

Evaluation

Layer What Detail
Offline task suite ≈ 300 tasks per agent type, each a container image with seeded state and a programmatic checker (tests pass, database state, file diff) 5 trials per task; report success with CIs clustered by task, pass^k for reliability, cost and steps per success
Safety suite Injection tasks (tool outputs containing adversarial instructions), canary secrets, attempted policy violations Attack success rate, unsafe-action attempts, exfiltration of canaries: all must be zero or below a set bar
LLM judges Only for criteria without programmatic checks (report quality, tone) Validated against human labels; pinned judge versions
Release gate Any change to model, prompts, tools or policies Paired comparison on the same tasks; non-inferiority on safety
Online Task completion, human-intervention rate, user ratings, cost per session Sample trajectories weekly for failure taxonomy; new failures become offline tasks

Trade-offs

Decision Options Consideration
Isolation Containers vs gVisor vs microVMs vs full VMs Stronger isolation costs startup time and memory; microVMs are the usual choice for running untrusted code
Autonomy Approvals everywhere vs risk-tiered Too many approvals and users rubber-stamp them; tier by reversibility and blast radius
Architecture Single agent vs multiple agents Multiple agents multiply tokens and add coordination failures; use them when subtasks are parallel and separable
History Full history vs compaction Full history keeps caches warm and information intact; compaction bounds cost and context length

Failure modes

Failure Mitigation
Injection leads to data exfiltration Egress allow-list, no secrets in context, approvals for external sends, canary monitoring
Runaway loop repeating a failing call Step and cost budgets, repetition detection, structured errors
Volatile content early in the prompt (timestamps, user names) destroys cache hits Stable prefix ordering; cache hit rate as a dashboard metric
Non-idempotent retries cause duplicate side effects Idempotency keys, exactly-once semantics in the tool runtime
Tool schema change breaks deployed agents Versioned tools, contract tests in the eval suite
Eval environment drift makes scores move without a model change Pinned images, rerun a fixed baseline with every eval

What a strong candidate says that a weak one does not

  • Weak: "An LLM calls tools in a loop, run code in Docker." Strong: treats the sandbox, egress and secrets as a security design and explains exactly why the model can never see credentials.
  • Computes that input tokens dominate and that caching (and cache-friendly prompt layout) decides whether the product is affordable.
  • Makes the orchestrator durable and tool calls idempotent, because agents run for minutes and retry.
  • Evaluates reliability (pass^k), safety (injection success rate) and cost, not just average success, and gates releases on paired comparisons.
  • Turns production failures into new eval tasks.

G. Eval platform

Prompt. Build the evaluation platform for a lab: every training checkpoint gets a quick evaluation, every release candidate a full one, and researchers add new evals every week.

Numbers

Quantity Calculation Result
Full suite for a release candidate 150k items × 4 samples × ≈ 1k output tokens 6·10⁸ generated tokens
Compute for a 70B model at ≈ 10k tokens/s per 4-GPU replica 6·10⁸ / 10⁴ = 6·10⁴ replica-seconds ≈ 17 replica-hours ≈ 67 GPU-hours, plus judge-model tokens
Quick suite per checkpoint ≈ 5% of the full suite ≈ 3–4 GPU-hours; 30 checkpoints a day ≈ 100 GPU-hours per day
Smallest detectable difference 1,000-item eval at ≈ 70% accuracy unpaired SE of a difference ≈ 2 points, so gates need paired tests and larger sets

Architecture

flowchart LR
    DS[("Dataset registry<br/>versioned, hashed,<br/>public / private / held-out")] --> DEF["Eval definitions as code<br/>prompt, extraction, metric,<br/>sampling params"]
    CKP["Checkpoints and<br/>release candidates"] --> SCH["Scheduler<br/>priorities, preemptible GPUs"]
    DEF --> SCH
    SCH --> RUN["Inference workers"]
    RUN --> JDG["Judge service<br/>pinned, calibrated"]
    RUN --> RES[("Per-item results store")]
    JDG --> RES
    RES --> ST["Statistics: CIs, paired diffs,<br/>clustered SEs"]
    ST --> DB["Dashboards"]
    ST --> GATE{"Release gate<br/>non-inferiority tests"}
    CON["Contamination scanner<br/>vs training data index"] --> DS
  • Store per-item outputs, not just aggregates. Paired comparisons, error analysis and re-scoring with a fixed extractor all depend on it.
  • Eval definitions are code with versions: any change to a prompt template, few-shot set, answer extraction or sampling parameter creates a new version, so scores never silently change meaning.
  • Statistics by default: every number on a dashboard has a CI; comparisons against the baseline are paired; clustered SEs where items share a source (lab 15).
  • Gates use non-inferiority margins: "the candidate is not worse than production by more than 1 point on safety evals, with 95% confidence", rather than "the number went up".
  • Judges are models too: pinned versions, calibration sets with human labels, bias tests (position, length, self-preference), and re-validation when anything changes.
  • Data protection: held-out sets are access-controlled, canaried, and scanned against training data; contamination findings are reported with the scores.

Failure modes: a template tweak shifts scores (versioning); judge drift after a judge update (calibration set rerun); small noisy evals driving decisions (CIs, minimum sizes); contamination (scanner, held-out refresh); eval compute starved by training (reserved or preemptible capacity with priorities).

What a strong candidate says: per-item storage and paired tests by default; "evaluating the evaluator" (judge validation, label audits); explicit sample-size reasoning; gates with statistical margins; a process for retiring saturated evals.


H. Classic ranking and recommendation

Still common in Big Tech loops, and the patterns (retrieval then ranking, logging, position bias, online experiments) carry over to LLM products.

Prompt. Design a feed recommender for 100M daily users choosing from 10M items, with p99 latency under 200 ms.

Quantity Calculation Result
Requests 100M users × 20 feed loads per day / 86,400 s ≈ 23k QPS average; plan for 2–3× at peak
Funnel 10M items → ≈ 1,000 candidates → ≈ 200 → ≈ 50 shown Each stage affords a costlier model on fewer items
flowchart LR
    REQ["Request + user context"] --> CG["Candidate generation<br/>two-tower ANN, follows,<br/>trending: ≈ 1,000"]
    CG --> LR1["Light ranker: ≈ 200"]
    LR1 --> HR["Heavy ranker<br/>multi-task: click, like,<br/>dwell, hide"]
    FS[("Feature store<br/>online + offline")] --> HR
    HR --> RR["Re-rank: diversity,<br/>freshness, policy"]
    RR --> FEED["Feed"]
    FEED --> LOG[("Impression and<br/>engagement logs")]
    LOG --> TRN["Training pipelines"]
    TRN --> CG
    TRN --> HR
  • Key points to cover: training/serving feature consistency (the same feature code for both); position bias in logged data (position as a feature at training, fixed at serving, or randomized exploration); cold start for new items and users (content embeddings, including from an LLM); multi-objective ranking with explicit weights; A/B tests with guardrail metrics and novelty effects.
  • Failure modes: feedback loops that narrow content, training on delayed labels, feature leakage from the future, and popularity bias.
  • Strong answers quantify the funnel, separate retrieval recall from ranking precision, and describe how offline metrics are checked against online experiments.

Traps

  • Skipping the numbers, or doing them and never using them to make a decision.
  • Designing for 100× scale on day one instead of the stated load with a path to grow.
  • No evaluation story, or an evaluation story with no sample sizes and no gate.
  • "Fine-tune" as the answer to every quality problem before measuring whether retrieval, prompting or data is the cause.
  • Ignoring privacy, permissions and deletion until the interviewer asks.
  • Forgetting cost per request and what drives it.
  • Listing technologies (vector database brands, serving frameworks) instead of explaining mechanisms and trade-offs.

Tip

Practice each design out loud in 45 minutes with the answer template, then compare with the write-up above and note what you missed. Company-specific emphasis differs: see the company guides, for example NVIDIA for performance-heavy rounds and Anthropic for safety-aware system design.