LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 177 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/8
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/11
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageClustering and PCACore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/24
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernanceData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/16
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/19
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning & Test-Time Compute
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnAI Lab InterviewingAI Lab System Design Interview
🏗️HardSystem Design

AI Lab System Design Interview

Design AI lab systems with clear goals, scale math, APIs, data models, overload behavior, permissions, eval gates, and operational debugging paths.

26 min read
Learning path
Step 158 of 177 in the full curriculum
AI Lab Coding Interview: Python SystemsAI Lab Behavioral Interview

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

A system-design round asks you to turn ambiguous model-product requirements into a reliable backend. A strong answer is rarely the most complex architecture. It names the product goal, sizes the hard constraint, then adds queues, caches, model routing, eval gates, permissions, or human review only where requirements force them.

Use codebase, model-serving, RAG, support-automation, and deployment examples when you need a concrete neutral domain: code search, incident summarization, policy-gated billing credits, eval dashboards, and internal agent workflows have real latency, privacy, and debugging constraints.

The design round script

Open with:

I will keep the first design simple, size the constraints early, then add queues, caches, sharding, model routing, or eval gates only when the requirement forces them.

Then follow this order:

  1. Goal: who uses it and what success means.
  2. Requirements: functional and non-functional.
  3. Scale: QPS, tokens, tenants, documents, latency, retention.
  4. API: external contract and important internal interfaces.
  5. Data model: entities, indexes, isolation, retention.
  6. Architecture: simplest request path first.
  7. Reliability: retries, idempotency, backpressure, overload, failover.
  8. Safety/security: permissions, audit, abuse controls, rollback.
  9. Observability: metrics, logs, traces, support views.
  10. Rollout: beta gates, canaries, eval gates, kill switches.

Why start with the goal instead of Kafka, GPUs, or vector databases?

Answer

Because the right infrastructure depends on the product goal and constraints. A support lookup, a long-running coding task, and a model-serving scheduler have different latency, reliability, privacy, and eval requirements.

Design pattern taxonomy

Most frontier AI/backend prompts are combinations of these patterns. Identify the dominant pressure before drawing boxes.

PatternPrompt signalArchitecture movesFollow-up pressure
Model gatewaymulti-provider, teams, API keys, quotasauth, entitlements, route policy, quota buckets, request logstreaming, fallback semantics, budget caps, support replay
Inference schedulerlatency, batching, GPUs, overloadadmission queue, batcher, worker pool, KV/cache accounting, fairnesstail latency, starvation, preemption, 429 vs 503 policy
Permission-aware retrievalenterprise docs, ACLs, deletion, citationssource connectors, ACL snapshots, filtered retrieval, audit trailrevocation SLO, fail closed, hybrid search, stale index
Agent execution platformlong-running tasks, tools, repo accesstask state machine, sandbox, tool policy, event log, artifactscancellation, retries, secret handling, human review
Eval and rollout gatequality launch, regressions, red teamoffline evals, golden sets, canary gates, rollback triggersslice failures, noisy judges, metric ownership
Data ingestion platformconnectors, freshness, normalizationingestion jobs, versioned records, dead-letter queue, backfillschema drift, reprocessing, dedupe, deletion
Observability and supportrequest IDs, incidents, "why did this happen?"traces, decision records, support views, replayable metadataprivacy-safe debugging, retention, sampling
Abuse and safety controlpolicy, misuse, irreversible actionspolicy engine, rate limits, review queues, kill switchesfalse positives, bypass attempts, emergency disable

Use this table to avoid architecture soup. A model gateway prompt doesn't need a vector database unless the product asks for retrieval. A retrieval prompt doesn't need autonomous agent planning unless the user asks the system to take actions.

Follow-up response bank

Interviewers often stress the first design with a new constraint. Answer by naming the boundary you'll change.

Follow-upGood moveBad move
"Traffic spikes 10x"admission control, queue SLO, tier fairness, explicit 429 or 503 causeunlimited queues
"Permissions change quickly"ACL freshness SLO, tombstones, fail-closed sensitive sourcesretrieve first, filter after generation
"Provider is down"policy-approved fallback, circuit breaker, surfaced degraded modesilently change model behavior
"Users need cancellation"durable cancel flag, cooperative checks, sandbox terminationbest-effort UI button only
"Support asks why"request ID, policy version, route decision, retrieved IDs, traceraw logs with no decision record
"Eval passes but users complain"slice analysis, online canary metrics, incident cases into regression suiteargue offline eval is enough
"Costs doubled"token accounting, cache hit tracking, model route policy, budget alertsvague autoscaling

Scale math checklist

Every design should include one small calculation. It doesn't need perfect precision; it needs to expose the bottleneck.

SystemMinimum math
Gatewayrequests/minute, tokens/minute, worst-case output cap
Retrievaldocuments, chunks/document, embedding storage, update rate
Schedulerarrival rate, average service time, queue wait, GPU memory
Agent serviceconcurrent jobs, sandbox time, log/artifact storage, retry budget
Eval platformexamples per suite, runs per release, judge/model cost
Voice/chatp95 latency budget split across network, model, tools, synthesis
Ingestionsource QPS, backfill duration, dedupe key cardinality

Use this phrasing:

I will size the constraint that most affects the design. If that assumption changes, the architecture boundary I would revisit is X.

Serving math you should have ready

For any serving prompt, two numbers decide the design before you draw a single box: how much GPU memory the weights take, and how fast the KV cache grows per request. You don't need exact figures. You need to teach the interviewer that you know where the memory goes.

The weight footprint is the parameter count times the bytes per parameter:

Mweights=P×bM_\text{weights} = P \times bMweights​=P×b

Here PPP is the number of parameters and bbb is bytes per parameter: 2 for FP16 or BF16, 1 for FP8. An 8-billion-parameter model in BF16 is about 8B×2=168\text{B} \times 2 = 168B×2=16 GB of weights before you serve a single token.

The KV cache is the part that scales with traffic. Every token kept in context stores key and value vectors for each key/value head in every layer:

Mtoken=2×nlayers×nKV heads×dhead×pbytesM_\text{token} = 2 \times n_\text{layers} \times n_\text{KV heads} \times d_\text{head} \times p_\text{bytes}Mtoken​=2×nlayers​×nKV heads​×dhead​×pbytes​

The leading 2 is for the key and the value. For a whole batch, multiply by the batch size BBB and the sequence length SSS:

MKV=2×B×S×nlayers×nKV heads×dhead×pbytesM_\text{KV} = 2 \times B \times S \times n_\text{layers} \times n_\text{KV heads} \times d_\text{head} \times p_\text{bytes}MKV​=2×B×S×nlayers​×nKV heads​×dhead​×pbytes​

Plug in simple numbers so the scale is concrete. The GQA line shows why grouped-query attention (sharing key/value heads across query heads) is the standard memory lever:

serving-memory-math.py
1params = 8_000_000_000 2bytes_per_param = 2 # FP16 or BF16 3weights_gb = params * bytes_per_param / 1e9 4print("weights_gb:", weights_gb) 5 6n_layers, n_kv_heads, d_head, p_bytes = 32, 32, 128, 2 7kv_bytes_per_token = 2 * n_layers * n_kv_heads * d_head * p_bytes 8print("kv_bytes_per_token:", kv_bytes_per_token) 9print("kv_mb_per_token:", round(kv_bytes_per_token / 1e6, 2)) 10 11batch, seq = 16, 2048 12kv_gb = kv_bytes_per_token * batch * seq / 1e9 13print("kv_gb:", round(kv_gb, 1)) 14 15n_kv_heads_gqa = 8 # grouped-query attention shares KV across query heads 16kv_bytes_per_token_gqa = 2 * n_layers * n_kv_heads_gqa * d_head * p_bytes 17print("kv_gb_gqa:", round(kv_bytes_per_token_gqa * batch * seq / 1e9, 1))
Output
1weights_gb: 16.0 2kv_bytes_per_token: 524288 3kv_mb_per_token: 0.52 4kv_gb: 17.2 5kv_gb_gqa: 4.3

At batch 16 and 2K context, this multi-head-attention cache rivals weight memory. Switching from 32 to 8 key/value heads with GQA cuts it from about 17 GB to about 4 GB. First confirm that weights and runtime overhead fit; then KV cache often sets marginal batch and context capacity.

A serving prompt asks whether you can raise batch size to improve throughput. Which memory term should you check first, and why?

Answer

After confirming that weights and runtime overhead fit, check KV cache. Weight memory is fixed for a loaded model, while KV memory grows with batch size, sequence length, layers, and key/value heads. Doubling batch or context can exhaust remaining HBM.

Decision log habit

When a design has many possible components, keep a visible decision log:

DecisionChosenRejectedWhyReversal signal
Queue placementbefore provider callinside every adapterone overload policyadapter-specific SLO needed
Retrieval filterbefore rerank/generationpost-generation filterprivacy fails closednone for sensitive docs
Fallback modelpolicy-gatedautomatic on any errorbehavior may changeexplicit customer opt-in
Agent writeshuman-revieweddirect writesirreversible action risknarrow, reversible tool scope

This keeps the conversation inspectable. Interviewers can disagree with a choice and still see that the choice was deliberate.

45-minute board plan

Practice with a visible clock. A strong design round leaves time for follow-ups instead of spending 30 minutes drawing boxes.

TimeOutput
0-4 mingoal, users, success metric, top risks
4-9 minfunctional and non-functional requirements
9-14 minone scale calculation that exposes the bottleneck
14-20 minAPI and durable data model
20-28 minrequest path with the smallest architecture that works
28-35 minreliability, overload, permissions, and support/debug flow
35-40 minrollout, eval gate, and rollback path
40-45 mintradeoffs, reversal signals, and interviewer follow-ups

If the interviewer interrupts early, jump to the dominant constraint:

The part that most changes the design is constraint. I will size that first, then show the request path it forces.

Mock design prompts

Treat each prompt like a 45-minute design round. First write requirements, scale math, API, data model, request path, failure modes, and rollout plan. Then open the solution guide.

Prompt 1: model gateway for enterprise teams

Design an API gateway for teams calling multiple LLM providers through one company platform.

Prompt details:

  • Each organization has workspaces, users, API keys, and model access rules.
  • The gateway must enforce requests/minute, tokens/minute, and monthly spend limits.
  • Support needs a request ID that can explain which route, model, policy decision, and overload state happened.
  • Some models are beta-only and must be gated.
  • Traffic can spike 10x during customer-support incidents.

Clarifying questions to ask:

  • Are clients streaming responses, batch jobs, or both?
  • Should spend limits be hard stops, soft alerts, or tier-dependent?
  • Which decision must support explain first: auth failure, quota failure, route choice, or provider failure?
Solution guide

Strong answer shape:

  1. Goal: reliable multi-model access with debuggable controls.
  2. API: POST /v1/responses, GET /v1/requests/{id}, admin endpoints for keys and limits.
  3. Data model: organization, workspace, key, route policy, model entitlement, usage bucket, request log.
  4. Request path: gateway -> auth -> quota estimate -> route policy -> admission queue -> provider adapter -> stream.
  5. Overload: return 429 with Retry-After when this tenant, key, or client exceeds its limit. Return 503 with a retry hint when healthy callers can't be admitted because fleet or provider capacity is exhausted. Route to an approved fallback only when product policy allows the behavior change.
  6. Observability: request ID, model, token estimate, queue wait, provider latency, error class, policy version.
  7. Rollout: canary new routes, kill switch beta models, regression tests for auth and quota bypass.

Common misses: no support path, no versioned policy record, no overload rejection, and no separation between authentication and authorization.

Follow-up guide

If asked about streaming, reserve quota from an estimate before admission, cap output length, then reconcile actual tokens at the end of the stream. If asked about fairness during a 10x spike, split queues by organization or tier so one incident can't starve everyone else. If asked about beta models, answer with a versioned entitlement check and a kill switch:

The gateway should log policy_version, entitlement_id, route_id, and quota_bucket_id on every request so support can explain both accepted and rejected traffic.

Prompt 2: permission-aware enterprise retrieval

Design retrieval for an internal assistant that answers employee questions from company documents.

Prompt details:

  • Documents come from multiple systems with different ACL formats.
  • Permission changes and deletions must take effect quickly.
  • Answers must cite sources.
  • The assistant must not retrieve and then filter private documents after generation.
  • Admins need auditability for "why did this answer use this document?"

Clarifying questions to ask:

  • What is the revocation target: seconds, minutes, or hours?
  • Can indexes be physically separated by tenant, or must filters enforce isolation?
  • Should the assistant fail closed when ACL freshness is unknown?
Solution guide

Strong answer shape:

  1. Ingestion: connector workers pull content plus ACL snapshots and write immutable document versions.
  2. Indexing: tenant or workspace isolation plus ACL metadata filters; deleted docs move to a tombstone state.
  3. Query path: auth context -> eligible corpus filter -> hybrid retrieval -> rerank -> answer with citations.
  4. Freshness: connector lag metric, ACL refresh jobs, deletion queue, and emergency purge path.
  5. Audit: query ID, user identity, eligible filters, retrieved doc IDs, citation IDs, policy version.
  6. Evals: recall slices by source, permission-denied tests, deletion tests, faithfulness checks.
  7. Failure mode: if ACL state is stale or unknown, fail closed for sensitive sources.

Common misses: filtering after generation, no deletion story, no citation IDs, and no way to explain eligibility.

Follow-up guide

If asked about deletion, describe a fast tombstone path first, then slower compaction of embeddings and chunks. If asked about stale permissions, define a freshness SLO per source and fail closed for sensitive sources when the ACL snapshot is too old.

For auditability, store enough to replay the eligibility decision: user identity, groups, source ACL version, query filters, retrieved chunks, citations shown, and model response ID. That lets an admin answer "why this document?" without exposing unrelated private documents.

Prompt 3: long-running coding agent service

Design a service that accepts repository tasks and runs a coding agent asynchronously.

Prompt details:

  • Users submit a repo, branch, task prompt, and tool permissions.
  • Jobs can run for 30 minutes and may need retries or human review.
  • The agent can create commits, run tests, and leave artifacts.
  • Users need live progress, cancellation, logs, and final diff review.
  • Secrets and production systems must be protected.

Clarifying questions to ask:

  • Is the service allowed to push branches, or should it only produce a patch artifact?
  • Which tools need network access, and which should run offline?
  • What happens when a user cancels during a tool call or test run?
Solution guide

Strong answer shape:

  1. API: create task, get task status, stream events, cancel task, list artifacts.
  2. State machine: queued, provisioning, running, blocked, review, failed, canceled, complete.
  3. Execution boundary: sandbox with scoped repo checkout, network policy, secret redaction, time and disk limits.
  4. Persistence: task row, run attempts, tool calls, logs, artifacts, branch/commit refs, cancellation flag.
  5. Recovery: checkpoint workspace state, retry transient infra failures, never replay unsafe writes without idempotency.
  6. Observability: per-tool latency, test results, token use, queue time, sandbox exits, reviewer actions.
  7. Rollout and safety: permission presets, allowlisted tools, audit log, kill switch by tool or model route.

Common misses: no cancellation semantics, no sandbox boundary, no artifact model, and no distinction between retrying a read and replaying a write.

Follow-up guide

If asked about retries, separate infrastructure retries from agent-action retries. Retrying a sandbox provision is safe; replaying a commit, comment, or external API write needs idempotency or human review.

If asked about cancellation, make it cooperative and durable: set a cancellation flag, stop scheduling new tool calls, terminate the sandbox after a grace window, persist partial logs, and mark artifacts as incomplete. If asked about secrets, say the sandbox receives scoped, short-lived credentials and the event log redacts values before storage.

Why is a support/debug path part of the design, not an afterthought?

Answer

Production AI products fail in ways users and operators need to inspect. Request IDs, traces, eligible documents, model choice, policy decisions, and overload state let support debug without guessing.

Drill 1: API gateway and rate-control plane

The gateway is the front door. It authenticates API keys, resolves workspace and organization limits, estimates request cost, routes to a model or queue, and emits a request ID that support can follow.

Diagram

Design checklist:

  • API keys map to workspace and organization.
  • Limits apply across requests/minute, tokens/minute, model, and tier.
  • Request IDs appear in responses and logs.
  • Tenant or client limits return 429; fleet or provider overload returns 503. Both carry a request ID and a bounded retry hint instead of silent queue growth.
  • Beta features are gated by explicit version or feature flags.
  • Rollout has canaries, kill switches, and regression checks.

Use Python to sanity-check rate math before drawing capacity boxes:

gateway-token-budget.py
1requests_per_minute = 4_000 2avg_input_tokens = 1_200 3avg_output_tokens = 450 4tokens_per_minute = requests_per_minute * (avg_input_tokens + avg_output_tokens) 5tokens_per_second = tokens_per_minute / 60 6 7print("tokens_per_minute:", tokens_per_minute) 8print("tokens_per_second:", round(tokens_per_second))
Output
1tokens_per_minute: 6600000 2tokens_per_second: 110000

The estimate is an admission-time reservation, not the final bill. A streaming response needs a maximum output budget, then a reconciliation step when the stream ends:

streaming-quota-reconciliation.py
1remaining_before = 10_000 2reserved_tokens = 1_800 3actual_tokens = 1_520 4 5remaining_after_admission = remaining_before - reserved_tokens 6remaining_after_reconcile = remaining_after_admission + (reserved_tokens - actual_tokens) 7 8print("after admission:", remaining_after_admission) 9print("after reconcile:", remaining_after_reconcile)
Output
1after admission: 8200 2after reconcile: 8480

Drill 2: inference scheduler

For LLM serving, the scheduler is where latency, cost, and fairness meet. NVIDIA documents in-flight batching as a way to interleave context and generation work so GPUs are used more efficiently while latency stays under control.[1]Reference 1Paged Attention, IFB, and Request Scheduling.https://nvidia.github.io/TensorRT-LLM/features/paged-attention-ifb-scheduler.html

Serving physics first

Before any scheduler diagram, separate the two work phases:

PhaseWhat happensTypical boundMetric it drives
PrefillProcess the full prompt into first-token KVOften compute-boundTTFT (with queue wait)
DecodeEmit one token at a time using cached KVOften memory-bandwidth-boundITL / TBT and TPOT

That split is why dual SLOs matter: a design can meet mean tokens/sec while still failing stream feel (bad ITL) or first-token UX (bad TTFT). Chunked prefill, separate prefill/decode pools, and prefill/decode disaggregation are answers to this physics, not optional jargon.

Metrics to name in the lab loop

  • Time to first token (TTFT): arrival → first output token (queue + prefill + first token).
  • Inter-token latency (ITL) / time between tokens (TBT): each gap after the first token; use the distribution (including tail) for stream feel.
  • Time per output token (TPOT): mean decode pacing after the first token (not a synonym of ITL).
  • Queue wait time before admission or first scheduled work.
  • p95 and p99 end-to-end latency, plus p95/p99 of TTFT and ITL when the product streams.
  • Fleet goodput / admitted RPS under dual TTFT and ITL SLOs (raw tokens/sec without SLO attainment is not capacity).
  • Tokens per second only with a label: per-request decode rate, fleet aggregate, or prefill rate. Undifferentiated TPS is not a substitute for ITL or TPOT.
  • GPU utilization.
  • Error rate and overload rejections.
  • Cost per successful request.

Serving toolkit (when to reach for each)

LeverWhat it fixesReach for it when
PagedAttention / paged KVKV fragmentation and rigid block allocationLong contexts or high concurrency thrash contiguous KV slots
Continuous (iteration-level) batchingMid-flight admit/finish without waiting for the slowest sequenceStatic batches waste GPU on finished or padded slots
Prefix / radix cacheReuse shared prompt prefixesMany requests share system prompts or multi-turn history
Speculative decodingExtra draft tokens validated in parallelDecode is bandwidth-bound and a smaller draft model is cheap
Chunked prefillCap prefill burst length so decode keeps streamingLong prompts spike TTFT and stall in-flight decode
Prefill/decode disaggregationSeparate pools for the two phasesOne pool fails to meet dual TTFT and ITL SLOs together

Continuous batching and paged attention are orthogonal: continuous batching decides when sequences join or leave the batch; paged attention decides how KV blocks are laid out and freed. Name both mechanisms separately in an interview.

Model-fit scale math

If weights plus KV don't fit one GPU, say the next move in interconnect language: tensor parallelism (TP) for layer shards over high-bandwidth links (often NVLink within a node), pipeline parallelism (PP) across stages (more tolerant of inter-node links, pays bubble cost), and expert parallelism when MoE routing requires it. Always state the communication cost you accept for the fit.

Start capacity planning with a measured workload-specific fleet capacity, not a generic GPU estimate:

scheduler-headroom.py
1measured_capacity_tokens_per_second = 125_000 2expected_demand_tokens_per_second = 110_000 3 4headroom = measured_capacity_tokens_per_second - expected_demand_tokens_per_second 5headroom_percent = headroom / measured_capacity_tokens_per_second * 100 6 7print("headroom_tokens_per_second:", headroom) 8print("headroom_percent:", round(headroom_percent, 1))
Output
1headroom_tokens_per_second: 15000 2headroom_percent: 12.0

For an interview-sized overload policy, estimate queue wait before admission. This approximation deliberately stays simple: it treats tokens as homogeneous. A real scheduler tracks two resources separately (prefill token backlog vs active decode sequences / free KV blocks) and measured tail latency for each SLO.

Keep rejection ownership visible. 429 Too Many Requests says the caller exceeded a tenant, key, or client policy and could succeed after its quota window resets. 503 Service Unavailable says the service fleet or an upstream provider lacks capacity for an otherwise eligible request. A full tenant bucket can produce 429 even when GPUs are idle; a saturated fleet can produce 503 for a tenant that is under quota.

scheduler-admission.py
1def admit(queued_tokens: int, service_tokens_per_second: int, max_queue_wait_seconds: float) -> bool: 2 estimated_wait = queued_tokens / service_tokens_per_second 3 return estimated_wait <= max_queue_wait_seconds 4 5def admit_two_resource( 6 prefill_backlog_tokens: int, 7 prefill_tokens_per_second: int, 8 active_decode_sequences: int, 9 max_decode_sequences: int, 10 free_kv_blocks: int, 11 kv_blocks_needed: int, 12 max_prefill_wait_seconds: float, 13) -> bool: 14 """Sketch dual capacity: prefill backlog and decode/KV slots both must clear.""" 15 prefill_wait = prefill_backlog_tokens / prefill_tokens_per_second 16 decode_ok = active_decode_sequences < max_decode_sequences 17 kv_ok = free_kv_blocks >= kv_blocks_needed 18 return prefill_wait <= max_prefill_wait_seconds and decode_ok and kv_ok 19 20print(admit(queued_tokens=20_000, service_tokens_per_second=125_000, max_queue_wait_seconds=0.25)) 21print(admit(queued_tokens=50_000, service_tokens_per_second=125_000, max_queue_wait_seconds=0.25)) 22print( 23 admit_two_resource( 24 prefill_backlog_tokens=10_000, 25 prefill_tokens_per_second=80_000, 26 active_decode_sequences=48, 27 max_decode_sequences=64, 28 free_kv_blocks=120, 29 kv_blocks_needed=16, 30 max_prefill_wait_seconds=0.25, 31 ) 32)
Output
1True 2False 3True

When should the system return 429 or 503 instead of queueing more work?

Answer

Reject before queueing violates latency or fairness. Use 429 when the caller's own quota or rate policy blocks admission. Use 503 when the shared fleet or provider is overloaded despite the caller remaining eligible. Include Retry-After when the service can estimate a safe retry window.

Drill 3: permission-aware retrieval

For enterprise retrieval, the critical rule is: don't retrieve private data and filter it after generation. Permission constraints must be part of candidate selection, ranking, and auditing.

Architecture pieces:

  • Connector ingestion workers with backpressure.
  • Per-document ACLs or delegated auth checks.
  • Tenant-isolated indexes or strict metadata filters.
  • Hybrid retrieval plus reranking.
  • Citation output with source IDs.
  • Deletion and retention jobs.
  • Offline evals for recall and answer faithfulness.
  • Support traces that show which documents were eligible.
Diagram

The ACL snapshot and hybrid index both feed candidate selection. That connection matters: unauthorized chunks shouldn't reach the reranker or model context.

For sensitive sources, encode the freshness decision as a fail-closed policy:

acl-freshness-policy.py
1def source_is_eligible(snapshot_age_seconds: int, freshness_slo_seconds: int, sensitive: bool) -> bool: 2 if sensitive and snapshot_age_seconds > freshness_slo_seconds: 3 return False 4 return True 5 6print(source_is_eligible(snapshot_age_seconds=20, freshness_slo_seconds=60, sensitive=True)) 7print(source_is_eligible(snapshot_age_seconds=90, freshness_slo_seconds=60, sensitive=True)) 8print(source_is_eligible(snapshot_age_seconds=90, freshness_slo_seconds=60, sensitive=False))
Output
1True 2False 3True

Filter tombstones and ACLs before ranking. The tiny fixture below makes the order visible:

acl-filter-before-rank.py
1documents = [ 2 {"id": "public-access-policy", "groups": {"employees"}, "deleted": False, "score": 0.82}, 3 {"id": "finance-plan", "groups": {"finance"}, "deleted": False, "score": 0.99}, 4 {"id": "old-handbook", "groups": {"employees"}, "deleted": True, "score": 0.95}, 5] 6user_groups = {"employees"} 7 8eligible = [ 9 document 10 for document in documents 11 if not document["deleted"] and document["groups"] & user_groups 12] 13ranked_ids = [document["id"] for document in sorted(eligible, key=lambda item: item["score"], reverse=True)] 14 15print(ranked_ids)
Output
1['public-access-policy']

Drill 4: long-running coding agents

Long-running agent infrastructure has to persist intent, tool calls, artifacts, checkpoints, logs, and permissions. The main design risk isn't just failed execution. It's uncontrolled execution.

Cover:

  • Task states: queued, provisioning, running, blocked, review, failed, canceled, complete.
  • Checkpoints for resumability.
  • Tool permission scopes and audit logs.
  • Secret redaction.
  • Git branch and conflict handling.
  • Streaming progress.
  • Cancellation and deadlines.
  • Evals for task success and regression.

Write legal transitions down before discussing workers. That prevents a cancellation or retry from jumping into an impossible state:

agent-task-state-machine.py
1ALLOWED_TRANSITIONS = { 2 "queued": {"provisioning", "canceled"}, 3 "provisioning": {"running", "failed", "canceled"}, 4 "running": {"blocked", "review", "failed", "canceled"}, 5 "blocked": {"running", "review", "failed", "canceled"}, 6 "review": {"running", "complete", "canceled"}, 7 "failed": set(), 8 "canceled": set(), 9 "complete": set(), 10} 11 12def can_transition(current: str, target: str) -> bool: 13 return target in ALLOWED_TRANSITIONS[current] 14 15print(can_transition("running", "review")) 16print(can_transition("complete", "running"))
Output
1True 2False

Retries need a policy boundary too. Reads and sandbox provisioning can retry automatically. External writes need an idempotency key or review:

agent-retry-policy.py
1def retry_mode(action: str, has_idempotency_key: bool = False) -> str: 2 if action in {"repo_read", "sandbox_provision"}: 3 return "automatic" 4 if has_idempotency_key: 5 return "automatic-with-idempotency" 6 return "human-review" 7 8print(retry_mode("repo_read")) 9print(retry_mode("create_commit")) 10print(retry_mode("post_comment", has_idempotency_key=True))
Output
1automatic 2human-review 3automatic-with-idempotency

Drill 5: eval gates and staged rollout

An evaluation monitor isn't just a dashboard. It turns fixed expectations and incident discoveries into a regression suite, then blocks launch when a critical slice fails.

eval-launch-gate.py
1checks = { 2 "retrieval_recall": (0.94, 0.92), 3 "citation_faithfulness": (0.93, 0.95), 4} 5permission_leaks = 0 6 7failures = [ 8 name 9 for name, (observed, minimum) in checks.items() 10 if observed < minimum 11] 12if permission_leaks > 0: 13 failures.append("permission_leaks") 14 15print("launch_allowed:", not failures) 16print("failures:", failures)
Output
1launch_allowed: False 2failures: ['citation_faithfulness']

Keep online canaries reversible. Offline evals can pass while latency, provider errors, or permission failures regress under real traffic:

canary-rollout-decision.py
1def rollout_decision(error_rate: float, p95_latency_ms: int, permission_failures: int) -> str: 2 if permission_failures > 0: 3 return "rollback" 4 if error_rate > 0.01 or p95_latency_ms > 900: 5 return "hold" 6 return "expand" 7 8print(rollout_decision(error_rate=0.004, p95_latency_ms=720, permission_failures=0)) 9print(rollout_decision(error_rate=0.004, p95_latency_ms=720, permission_failures=1))
Output
1expand 2rollback

Common serving misconceptions

Stale claimWhy it's outdatedCurrent answer
"Static batching with fixed padding is fine for LLM inference"It pads every request to the longest sequence and holds the batch until the slowest one finishes, wasting GPU on padding and blocking short requests behind long onesTwo fixes, not one: continuous (iteration-level) batching admits and finishes sequences mid-flight so the GPU stays busy on real tokens; paged attention lays out KV in non-contiguous blocks so finished sequences free memory without reshaping the whole batch[1]Reference 1Paged Attention, IFB, and Request Scheduling.https://nvidia.github.io/TensorRT-LLM/features/paged-attention-ifb-scheduler.html[2]Reference 2Efficient Memory Management for Large Language Model Serving with PagedAttention.https://arxiv.org/abs/2309.06180
"Slurm is the only scheduler for multi-node GPU clusters"Slurm still fits bare-metal HPC training, but it isn't the only option for serving or enterprise platformsKubernetes with KubeRay and Ray Serve orchestrates training and inference on the same substrate, sometimes in a hybrid setup that bursts training onto Slurm[3]Reference 3KubeRay and Ray clusters on Kubernetes.https://docs.ray.io/en/latest/cluster/getting-started.html
"Quantization always wrecks quality"True for some naive low-bit schemes, not every calibrated methodFP8 roughly halves BF16 weight bytes; 4-bit methods such as AWQ and GPTQ can reduce weight memory further. Quality and speed remain workload- and runtime-dependent, so evaluate both before release.[4]Reference 4AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration.https://arxiv.org/abs/2306.00978[5]Reference 5GPTQ: Accurate Post-Training Quantization for Generative Pre-Trained Transformershttps://arxiv.org/abs/2210.17323

For each correction, identify old approach's failure and replacement mechanism.

Failure modes to avoid

  • Starting with implementation technology before naming user value.
  • Caching without invalidation, privacy, or freshness.
  • Monitoring without exact metrics.
  • Ignoring overload and support/debug needs.
  • Treating safety as a slogan instead of evals, permissions, staged rollout, and rollback.
  • Forgetting that agent systems need reversible actions and audit trails.
Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.A support engineer must explain why one gateway request used a beta model, waited in a queue, and then returned an admission error. Which design choice best distinguishes a tenant 429 from fleet overload 503?

Correct answer: Attach a request ID to the response and store route decision, model, entitlement or policy version, quota state, queue wait, overload state, and error class.

Support needs a per-request decision trail beyond aggregate metrics or raw logs. Quota state identifies a caller-owned 429, while queue and fleet overload state identify a service-owned 503. Request IDs plus policy, route, model, and error metadata make that distinction inspectable.

2.A streaming gateway request starts with 10,000 tokens remaining in a quota bucket. The gateway reserves 1,800 tokens at admission, and the stream actually uses 1,520 tokens. What should the bucket show after admission and after reconciliation?

Correct answer: 8,200 after admission and 8,480 after reconciliation

Admission uses the maximum estimate, so 10,000 - 1,800 leaves 8,200 while the stream is running. After completion, the unused reservation is returned: 1,800 - 1,520 = 280, so the reconciled balance is 8,480.

3.An under-quota tenant sends a request while the shared inference fleet is saturated. The scheduler estimates 0.4 seconds of queue wait against a 0.25-second objective, and admission would delay higher-priority traffic. What should it return?

Correct answer: Reject with 503 and a retry hint because shared fleet capacity, not this tenant's quota, prevents safe admission.

Queues are useful only while they protect latency and fairness. This caller remains under quota, so 429 would assign the failure to the wrong boundary. Shared capacity is unavailable, making 503 the correct service-owned overload response.

4.An enterprise retrieval system has three candidate chunks: public-access-policy is visible to employees, not deleted, score 0.82; finance-plan is visible to finance, not deleted, score 0.99; old-handbook is visible to employees, deleted, score 0.95. The user is only in employees. Which chunk should reach reranking?

Correct answer: public-access-policy only

ACL and deletion filters must run before ranking or generation. The finance document has the highest score but the user lacks its group, and the old handbook is tombstoned, so only the non-deleted employee-visible document is eligible.

5.An internal assistant has a sensitive HR source with an ACL snapshot age of 90 seconds and a freshness SLO of 60 seconds. A non-sensitive public handbook source also has a snapshot age of 90 seconds and a 60-second SLO. Under a policy that fails closed for sensitive sources when ACL freshness is stale, which source should be eligible for retrieval?

Correct answer: Only the public handbook is eligible; stale ACLs exclude sensitive sources until refreshed.

The fail-closed rule applies to sensitive sources whose ACL snapshot is older than the freshness SLO. The HR source is blocked until its ACL state is fresh, while the non-sensitive source is not excluded by that specific policy. Checking after generation would leak private candidates too late.

6.A long-running coding-agent service is recovering after failures. Which retry policy matches the required safety boundary?

Correct answer: Retry repo reads and sandbox provisioning automatically, but require idempotency or human review before replaying commits, comments, or other external writes.

The safety boundary is side effects. Read-only work and infrastructure setup can usually retry automatically, but commits, comments, and external API writes may already have partially succeeded. Those actions need an idempotency key or review before replay.

7.A coding-agent task is running tests in a sandbox when the user cancels. The service must preserve an audit trail and avoid new side effects. What cancellation behavior is correct?

Correct answer: Persist a cancel flag, stop scheduling new tool calls, terminate the sandbox after a grace window, save partial logs, and mark artifacts incomplete.

Cancellation must be durable and cooperative. The service records the user's intent, prevents new tool work, gives the sandbox a bounded chance to stop, preserves partial evidence for support and audit, and labels incomplete outputs instead of pretending the run completed cleanly.

8.An eval launch gate has retrieval_recall 0.94 with a minimum of 0.92, citation_faithfulness 0.93 with a minimum of 0.95, and zero permission leaks. What should the gate do?

Correct answer: Block launch because citation_faithfulness is below its threshold.

A launch gate blocks when any required check fails. Retrieval recall passes and permission leaks are zero, but citation faithfulness is 0.93 against a 0.95 minimum, so the release should not proceed until that slice is fixed or the gate is deliberately changed.

9.Offline evals have passed. A canary observes error_rate 0.004, p95 latency 720 ms, and 1 permission failure. The rollout policy says any permission failure rolls back; error_rate over 0.01 or p95 over 900 ms holds; otherwise expand. What should the rollout controller do?

Correct answer: Rollback, because a permission failure overrides otherwise healthy latency and error metrics.

The rollback rule is triggered by any permission failure, even though the error rate and latency are within their expand thresholds. Offline evals reduce launch risk, but online canaries must remain reversible when real traffic exposes safety or permission regressions.

10.A candidate claims the inference fleet is healthy because aggregate tokens per second rose 20% after a config change. TTFT p95 and ITL p95 both regressed past SLO. What is wrong with using undifferentiated TPS as the capacity signal?

Correct answer: Raw tokens/sec without dual TTFT/ITL (or goodput under those SLOs) is not capacity; prefill and decode can move in opposite directions, and TPS is not a substitute for ITL or TPOT.

Lab serving rounds expect TTFT, ITL/TBT, TPOT, and goodput under dual SLOs. Undifferentiated TPS can rise while stream feel and first-token latency fail. Name the metric family and the prefill vs decode physics before treating throughput as success.

10 questions remaining.

Next Step
Continue to AI Lab Behavioral Interview

You'll translate production engineering evidence into values, judgment, disagreement, incident, and mission-fit answers without sounding rehearsed.

PreviousAI Lab Coding Interview: Python Systems
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

Paged Attention, IFB, and Request Scheduling.

NVIDIA · 2026

https://nvidia.github.io/TensorRT-LLM/features/paged-attention-ifb-scheduler.html

Efficient Memory Management for Large Language Model Serving with PagedAttention.

Kwon, W., et al. · 2023 · SOSP 2023

https://arxiv.org/abs/2309.06180

KubeRay and Ray clusters on Kubernetes.

Ray (Anyscale) · 2026

https://docs.ray.io/en/latest/cluster/getting-started.html

AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration.

Lin, J., et al. · 2023 · MLSys 2024

https://arxiv.org/abs/2306.00978

GPTQ: Accurate Post-Training Quantization for Generative Pre-Trained Transformers

Frantar, E., et al. · 2023 · ICLR 2023

https://arxiv.org/abs/2210.17323

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.