LearnThatStack Ace your next interview

MLOps & Model Deployment.
Cheat sheet.

Quick reference for MLOps & Model Deployment - sectioned for fast scanning. Skim the part you're shaky on, walk in confident.

Machine Learning & Data Science 9-section reference ~14 min read

30-second mental model

Term One line
Inference One prediction from one input. A math problem - reproducible in a notebook.
Serving The running system that answers prediction requests. An availability problem: queues, timeouts, p99.
Deployment The release event that puts version X behind serving. A change problem: approval, audit, rollback.
Model drift Real-world quality decays. Weights never change; the world they were fit to does.
Data drift Inputs moved. Measurable the moment traffic arrives, no labels needed.
Concept drift The input -> label rule moved. Only visible once labels land.
Training-serving skew Features at predict time differ from features at train time. Nothing throws an error.
Lineage data snapshot -> code commit -> image digest -> run -> artifact -> deployment. Explains; never detects.

Choose a serving shape

Pick batch, online, or streaming

Situation Shape Price you pay
Prediction does not depend on what the user just did (churn, nightly recs, lead ranking, pre-approvals) Batch -> write to a table/cache, serve as a key lookup Stale between runs; ignores the current session
Input arrives in the request and a user is waiting Online request-response Latency budget, autoscaling, tail risk
Signal is the event sequence itself ("7 transactions in 2 minutes"), no user request triggers it Streaming Windowing, late/out-of-order events, exactly-once, its own on-call

Most "we need streaming" is really "we need one fast feature lookup". Precompute that feature and stay request-response.

Decide what to return when the model is unavailable

Domain Mode Return
Recs, ranking, ads Fail open Global default, popularity ranking, or last cached prediction
Fraud, credit, medical triage Fail closed Decline / manual review - never a guess
  • Hard timeout + circuit breaker in front of the call. A slow model is worse than a dead one.
  • Identical response schema in both paths; add a degraded: true + reason code.

Tag every degraded response in the log, or the next retrain learns from your own fallbacks.

Order the fallback tiers (fire per failed component, not one global switch)

Failure Degraded path
Online feature store times out Cached features + staleness flag
Features missing Feature-light model variant
Model server down Previous model version
That too Precomputed heuristic / popularity from cache
That too Static default per segment

Reproducibility, versioning, registry

Log this for every training run

git commit of training and preprocessing code; dataset version or snapshot id; all hyperparameters + seeds; library versions and hardware; metrics on a fixed eval set; artifact + its hash.

Pin a run so it rebuilds in six months

Target metric-equivalence, not bit-exactness (bit-exact GPU determinism costs real training speed).

Axis Pin as
Code Commit hash, config stored as a run artifact (not read live)
Environment Image digest, never a floating tag
Data Immutable snapshot id
Randomness Seeds + the framework version that gives them meaning

The one people skip is the environment. A :latest-style tag reproduces next week and fails next year.

Version a dataset (pin bytes, not a filter)

# same query + same cutoff != same rows, once backfills and deletes land
run = {"dataset": "orders", "snapshot": "s_00147", "sha256": "3ab9..."}
# rebuild -> load s_00147, verify hash, retrain -> same AUC within noise

Two workable shapes: immutable snapshot copy + content hash, or an append-only table format with retained snapshots and the snapshot id in the run manifest. Retention must outlive your audit window. Erasure requests delete rows from old snapshots - document which runs are now approximate.

Promote staging -> production in a registry

Promotion is an alias change, not a deploy. The artifact bytes never move.

  1. Register artifact after training, attach metrics + lineage.
  2. Staging gate: held-out set + a shadow window.
  3. Human or policy approval, then flip the alias. Archive the old version, never delete.
Serving resolves Get Lose
Alias, on a refresh loop Instant rollback Instant accidental rollout
Pinned version Control Redeploy needed to fix

If serving pins a hard version, "promotion" changes nothing until someone redeploys.

Make the training job refuse to run

...when dataset hash, commit hash, or image digest is unknown. Record identifiers, not copies. One untracked notebook breaks the whole chain.

Features and skew

Keep training and serving features identical

One definition, two reads: training reads the offline store, serving reads the materialized online value. Neither recomputes the transform locally. The moment someone computes a feature inline in serving code, skew is back and nothing warns you.

Skew source Tell
Duplicated logic in two languages Values close but not equal
Different null-fill defaults Serving zeros where training had a mean
Encoder rebuilt at serve time Category ids shifted
Windowed aggregate over partial day Offline avg over 24h, online avg over "so far"

Defense: log the exact feature vector used at prediction time, then diff it against the training row.

Use point-in-time (as-of) joins

The offline read must return the value as it stood at the event timestamp. Using today's value leaks the future and inflates offline scores.

Skip the feature store when

One model, one nightly job, or features computed from the request payload alone. A shared transformation library is simpler and just as safe. The store earns its network hop, its uptime risk, and its bill once several models share features across teams.

Debug "offline and online disagree"

Pin one entity + one timestamp and replay end to end. Compare the logged served vector against a recompute - not against a fresh pipeline run; the pipeline is the suspect.

Cause Fix
Point-in-time leakage (offline join sees post-request data) As-of join
Staleness (batch job later corrected the value) Both are right at their own time - as-of join, not a patch
Divergent code (streaming transform hand-written) Single definition
Type / null handling differences Shared defaults

Run this comparison continuously on a small sample, not only when someone complains.

Monitoring

Watch four layers, in arrival order

Layer Signals Response
Service health request rate, error rate, p50/p99, saturation Page
Input health null rate, schema change, feature distributions Page only on null/constant/schema break
Output health prediction distribution, per-class rate Dashboard + ticket
Quality precision, recall, business metric (needs labels) Page on confirmed drop

Never page overnight for a two-point move in a feature histogram. That is how teams learn to ignore the pager.

Pick a drift test

Feature type Test Threshold
Numeric PSI < 0.1 stable, 0.1-0.25 moderate, > 0.25 act
Numeric (alt) Two-sample KS Effect size, not raw p-value
Categorical Chi-square + new/vanished category check Any new or dropped level = investigate

PSI wins because its thresholds behave like an effect size. With enough traffic a p-value fires on everything.

Choose what to monitor (not every column)

Top features by importance; anything from a flaky upstream source; the model's own output distribution (summarises many inputs at once). Slice by country, device, app version - a shift confined to one slice is a pipeline change, not the world moving.

Tell a broken pipeline from concept drift

Broken pipeline Concept drift
Abrupt and structural: null rate 2% -> 40%, column collapses to one value, range jumps 1000x after a unit change Gradual, inputs stable, error rises
Hits every model sharing that feature at once Hits one model's task
Lines up with a deploy or schema event No event lines up
Reverses instantly when upstream is fixed Survives a retrain

Rule out the pipeline first - it is far more common and far cheaper to fix. The nasty case is slow rot (a source table gradually stops populating for a growing share of users); catch it with freshness and coverage monitors on the source, not distribution monitors on the feature.

Detect degradation without labels

  • Prediction distribution shift - cheapest alarm (avg fraud score halves overnight).
  • Input drift weighted by feature importance, not flat across every column.
  • Weak labels: human-review a few hundred sampled predictions weekly.
  • Proxy outcomes: acceptance rate, click-through, manual override rate - all move before the real label.

Two blind spots: drift without harm (false alarms - tie thresholds to observed impact) and harm without drift (concept drift, which no input monitor can see).

Monitor many models at once

Standardize emission, centralize compute, tier the alerting. One shared logging library emits the same envelope everywhere: model_id, version, sampled feature vector, prediction, latency, request_id. One drift job reads the store for all models, baselines pulled from each model's training snapshot. Monitoring attaches at registration, not as a follow-up ticket.

Cost bites twice: store sketches/histograms and sample rather than keeping full vectors, and watch cardinality - model x version x slice x feature will melt a TSDB.

Retraining

Give each trigger the response it deserves

Trigger Timing Response
Metric drop Last, but the only one tied to real harm Page
Drift alarm Early, often harmless Open an investigation - never an auto-retrain
Schedule On time, often unnecessary Run the pipeline anyway

The underrated case for a cadence: a pipeline that has not run in five months will fail the day you need it urgently. Shorten the cadence when label latency is long.

Promote a challenger without shipping a worse model

  • Re-score both models on the same recent holdout with the same eval code. Comparing a fresh challenger against the champion's stale historical score is the classic bug.
  • Default is no promotion. Promote only if the gain exceeds run-to-run noise (measure noise by training the same recipe twice). A tie keeps what is serving.
  • Add per-segment no-regression rules; an overall gain can hide a collapse in one country.
  • Add prediction-distribution and feature-schema checks - they catch a broken input before quality tests run.
  • Full automation is fine. Automatic promotion straight to 100% of traffic is not.

Retrain vs fine-tune

Retrain from scratch Fine-tune
Cost High Low
Lineage One clean run A chain - replay every step
Risk - Inherits old bias; recent-only data erases competence on old segments
Use when Distribution genuinely moved, label definition changed, audit needed Base model expensive, new data small (normal for large pretrained models)

Diagnose "accuracy slid for three months"

  1. Confirm the metric is real: label delay, changed denominator, new logging path. Recompute on a fixed cohort.
  2. Segment before modeling. Average accuracy often falls because a weak segment grew (new country, new device class, bot wave), not because anything got worse.
  3. Only then fix by cause: grown weak segment -> more data or its own treatment; genuine decay -> retrain on a shorter window with a fresh holdout, compared to the incumbent on the same recent data.

Retraining first hides a mix change, and the slide resumes a month later.

Release mechanics

Pick a rollout mechanism

Mechanism Answers Best when Blind spot
Shadow "Does the system survive?" Bad prediction is expensive/irreversible; serving path changed No labels, no clicks - proves nothing about being better. Doubles inference cost
Canary (1% -> 5% -> 25%) "Is this safe to release?" Risk is behavioral and traffic is large Needs volume + time; 1% of low traffic says nothing for days
Blue-green "Can I undo instantly?" Risk is operational (runtime upgrade, hardware) and you can validate offline No gradual signal at all
A/B "Is this better for the business?" Proving value before full rollout Slow; needs a pre-computed sample size

Choose from how fast you learn the model is bad: labels in seconds -> a small live slice teaches you within an hour; ground truth in two weeks -> a canary only proves the service does not crash. Then check for irreversible side effects (sent email, declined payment) and feature contracts (a new feature must exist in serving first).

A shadow model must never write anywhere.

Do not confuse canary with A/B

Canary A/B
Duration Minutes to hours To a pre-computed sample size
Randomize by Request User
Peeking Correct - halt on any regression Inflates false positives
Watches Errors, latency, gross output shift Conversion, revenue, retention vs control

Randomizing an A/B by request is the classic bug: one user sees both models and per-user metrics become meaningless. Canary first for safety, A/B after for value.

Auto-halt a canary on these

Signal Halt rule
Error rate Canary 5xx exceeds control by 0.5pp, or doubles it
Latency p99 20% above control for 5 consecutive minutes
Feature nulls / defaults Any spike past the shadow-run band - halts immediately (broken pipeline, not a worse model)
Prediction distribution Mean score or null-prediction rate outside the shadow-established band
Business metrics Rarely usable - a 5% slice lacks power to prove revenue harm in an hour

Guard every rule with a minimum sample count. Use sequential tests (rechecking a fixed threshold each minute manufactures false alarms). Exclude the opening minutes - cold caches and JIT inflate early tails. Past a few dozen models, learn each baseline from the control arm per rollout instead of hand-setting numbers.

Handle "canary wins on revenue, loses on p99"

  1. Is the tail real? Small canary = few p99 samples. Re-measure after warmup, on matched hardware, split by slice.
  2. Do upstream callers time out near that tail? Then slow predictions became errors and the lift is measured on survivors only.
  3. Convert to one currency: revenue cost per +100ms vs the measured lift. Inside the error budget and the lift wins -> promote, file the latency debt.
  4. Otherwise buy the tail back: distill/quantize, cache features, or route the heavy model to high-value traffic only.

Roll back a model

Easy half: keep the previous version warm and flip the alias or traffic weight.

Hard half - a model leaves state behind:

  • Predictions already written downstream stay wrong until you backfill.
  • Items shown / transactions blocked are now in the training data, so the next retrain inherits the bad run.
  • The old artifact may need a feature schema or library version that has since moved.

Make it rehearsed: pin each model version to its feature-pipeline version and image digest, keep last-known-good warm (not cold), tag every stored prediction with the model version that made it, and test the rollback before you need it.

Gate before production (roughly by hit rate)

  1. Slice metrics vs the current production model, with a no-regression threshold on protected and high-value slices. Aggregate accuracy is the weakest gate and the one most teams stop at.
  2. Serving parity: score a fixed sample through the real serving path, compare to offline. Any mismatch is skew.
  3. Behavioral checks: known input-output invariants and directional expectations.
  4. Load: p99 at expected peak, memory ceiling, cold-start time.
  5. Schema contract: the model must reject unexpected types loudly, not silently impute.

Anything you cannot check before release becomes a canary metric.

Latency, capacity, cost

Divide the latency budget (budget the tail, not the mean)

200ms p99 product budget -> ~120ms for the service after client network, gateway, rendering:

Hop Budget
Feature fetch 40ms (usually biggest, the only remote dependency)
Transform + validation 10ms
Model forward pass 45ms
Post-process, rank, serialize 15ms
Unspent slack ~15% for retries, GC pauses, a cold replica

Per-hop timeouts must sum to less than the budget, not equal it. Fan-out breaks the arithmetic: 8 parallel feature calls cost the slowest of 8, so the group p99 is far worse than any single p99. Hedge, or accept a partial vector with defaults.

Cut inference latency, in this order

Measure the breakdown first - quantizing a model that costs 4ms of a 90ms request buys nothing.

  1. Cut round trips: batch feature fetches into one call, cache slow-changing features near the server, precompute anything not request-dependent.
  2. Shrink the model: distillation, quantization, pruning, smaller architecture, compiled runtime.
  3. Serving mechanics: dynamic batching, warm pools, model pinned in memory.

Each lever has a cost: caching returns stale predictions, quantization loses a little quality, dynamic batching adds queue delay per request while raising throughput.

Reason about throughput vs latency under load

# Little's law: in_flight = arrival_rate * latency
in_flight = 2000 * 0.05   # -> 100 concurrent requests
  • Waiting 10ms to fill a batch of 32 can triple GPU throughput and adds 10ms to every request. Larger batches hold more activation memory - the ceiling is usually memory, not compute.
  • Past ~70% utilization, wait time grows faster than load and p99 becomes queue time, not model time.
  • Adding replicas fixes tail latency far more reliably than shaving ms off the forward pass.
  • Cap the batch wait window, not just batch size. Cap server concurrency so overload becomes a fast rejection, not a ten-second wait. Shed low-priority traffic before the tail collapses.

Set SLOs that mean something

  • Derive from the caller: checkout has 300ms, model gets 80ms -> objective is p99 < 80ms.
  • Measure at the client edge, rolling 28-day window. Server-side timers exclude queueing, feature fetch and network - they flatter you.
  • Availability counts usable answers, not status codes. A timeout that returns a default is still an HTTP 200.
  • Track p50 and p99 separately. Keep prediction quality as its own indicator - a service can be perfectly available and confidently wrong.
  • Spend the error budget on purpose: comfortably inside -> ship riskier models faster; burned -> freeze releases.

Cut cost with traffic tiering

Rank requests by expected value, match each tier to a cheaper path: logged-in checkout -> full model; cache miss on a mid tier -> distilled/quantized model; crawlers, logged-out browsing, internal calls -> cached or precomputed. Precompute the few thousand hot entities in batch and reserve live inference for the long tail. Under pressure, degrade tiers in order rather than shedding traffic uniformly.

Tiering feeds itself: a segment routed to the weak model gets worse outcomes, which look like genuinely lower value next quarter.

Pitfalls that cost the most

  • The notebook-to-package seam: a feature transform rewritten by hand diverges silently. Package the artifact with its inference code.
  • Alerting on accuracy alone - labels arrive days late or never.
  • Comparing a fresh challenger against a stale champion score.
  • Pinning a query instead of pinning bytes.
  • An image tag instead of an image digest.
  • Untagged degraded responses feeding the next training set.
  • A rollback path that has never been rehearsed.
  • Mitigate first, diagnose second: flip to the last-good version, then find the renamed upstream column.
Found this useful? Pass it on.
Pro · $10/mo

The sheet is free. Pro goes deeper.

Pro opens the full question library behind every sheet, every refresher and a monthly AI allowance. One subscription, all formats.

Full question library All refreshers Cancel anytime