DEV Community

Cover image for Machine Learning System Design: The Framework That Wins Interviews
RONI DAS
RONI DAS

Posted on • Originally published at systemdesign.academy

Machine Learning System Design: The Framework That Wins Interviews

Ask most people to design a machine learning system and they start with the model. They reach for a transformer, or a gradient-boosted tree, or whatever architecture is fashionable that quarter, and they spend the interview tuning it in their heads. That instinct is exactly what the question is built to expose, because in a real ML system the model is the easy part. It is a small box in the middle of a much larger diagram, and it is usually the most replaceable component in it.

A machine learning system design interview is not asking you to invent a new model. It is asking whether you can take a vague business goal, something like show people more relevant posts, and turn it into a system that reliably produces good predictions on live traffic, keeps producing them as the world changes, and does so inside a latency budget measured in tens of milliseconds. The interesting work is almost never the architecture. It is how you frame the task, what you choose to optimize, where the labels come from, how features stay identical between training and serving, how you evaluate offline and confirm online, and how you notice when the whole thing quietly decays.

This piece is the long version of that framework. We will walk it in the order a strong candidate actually walks it: the two loops that make up any ML system, how to frame the problem and pick metrics, the feature store and the skew it exists to kill, how data and labels are where interviews are won or lost, the two-stage candidate-and-ranking pattern, the gap between offline evaluation and online A/B testing, the two ways to serve, and finally the monitoring that stops a live system from rotting in silence. Any specific latency, throughput, or catalog-size number here is an industry-typical range or an illustration for reasoning, not a measured figure from a particular company.

Two loops, one shared clock problem

The backbone of a good answer is seeing that an ML system is two loops that share artifacts but run on completely different clocks.

ml-system-deep diagram
The offline training loop and the online serving loop share one feature store.

The offline training loop runs on a schedule. It reads raw logged events, impressions, clicks, watches, purchases, from a data lake or warehouse, joins them with the features as they were at the moment each event happened, builds a labeled training set, trains a model, evaluates it offline, and if it passes, registers it in a model registry. This loop is allowed to be slow. It runs hourly, or daily, or weekly, and nobody is waiting on it in real time.

The online serving loop runs on every single request. It takes a live context, fetches the relevant features, generates candidates, ranks them, applies business and policy filters, returns the result, and logs everything it just did. This loop lives on the critical path of a user-facing response, so it is measured in milliseconds.

The two loops meet in the logs. Everything the serving loop shows becomes tomorrow's training data for the offline loop. That is elegant and it is also the source of the subtlest bug in all of ML, which we will get to. For now the point to internalize is that keeping these two loops straight, and keeping their feature computation identical, is what separates an answer that sounds like production from an answer that sounds like a notebook.

Framing: the honest first question is whether to use ML at all

Before any of that, you turn a fuzzy business goal into a precise ML task. And the first honest question is whether machine learning is even warranted.

If the problem can be solved with a rule, show newest first, block known-bad IPs, a heuristic baseline is the correct starting point. It is cheaper, easier to debug, trivial to explain, and it gives you the bar the ML model has to beat to justify its complexity. Saying this in an interview is a strength, not a hedge. It signals that you reach for ML because it beats the baseline on a metric that matters, not because a model is the more impressive thing to talk about.

When ML is warranted, you frame it as a concrete prediction task. Is this classification, will the user click? Regression, how long will they watch? Ranking, order these items by value? Getting this framing explicit shapes everything downstream, from the loss function to the evaluation metric.

Then you separate two kinds of metrics that beginners constantly conflate.

ml-system-deep diagram
Business goal to ML task to the split between the offline metric and the online metric.

The offline metric is what you train and evaluate against on logged data: AUC, log loss, precision at k, NDCG for ranking. It is fast to compute, repeatable, and it lets you iterate quickly. The online metric is what the business actually cares about: engagement, watch time, revenue, retention. It can only be measured on live traffic. These two do not move together perfectly. A model can improve offline AUC and do nothing, or even harm, the online metric.

The discipline that separates strong answers is refusing to declare victory on an offline metric alone, and always naming the online metric you would confirm the win with. Google's Rules of Machine Learning makes exactly this point: get the infrastructure and the metrics right before you get clever with the model, and be honest about the gap between the metric you can optimize and the outcome you actually want.

The feature store and the skew it exists to kill

If I had to name the single most important piece of ML-specific infrastructure in this design, it would not be the model. It would be the feature store, and it earns that place by solving one specific, damaging bug.

ml-system-deep diagram
The feature store gives one feature definition to both training and serving, killing train-serve skew.

Train-serve skew is the most common and most expensive failure in production ML. The setup is innocent. A data scientist computes a feature one way in a training pipeline, say average session length over the last 30 days, written in SQL over the warehouse. An engineer reimplements that same feature another way in the serving code, computed on the fly from a slightly different source with a slightly different window. The two definitions drift apart. The model is now trained on one distribution and served another, and quality drops in a way that is completely invisible to offline evaluation, because offline evaluation uses the training-time computation.

There is a subtler cousin, time-travel leakage: joining an event to a feature value that was only known after the event happened. That inflates your offline metrics beautifully and then collapses in production, because at serving time the future value does not exist yet.

A feature store fixes both by making one definition of each feature the source of truth. It has an offline store, usually columnar and in the warehouse, that serves point-in-time-correct values for training, meaning the value as it actually was at event time. And it has an online store, usually a low-latency key-value store, that serves the identical value to the ranker at request time. The training pipeline reads from the offline side, the serving path reads from the online side, and both read the same feature computed from the same definition.

When an interviewer hears you volunteer that you would use a feature store specifically to avoid train-serve skew, it reads as someone who has operated an ML system rather than only trained models. It is one of the cleanest signals in the whole interview.

Data and labels: where interviews are actually decided

The model is only as good as the labels behind it, which is why the data section is usually where these interviews are won or lost. There are three things a strong candidate always covers.

First, where the labels come from. Explicit signals, a purchase, a rating, are clean but sparse. Implicit signals, clicks, dwell time, are abundant but noisy and biased. A click can be a misclick, and a non-click can simply mean the item was never seen. That leads directly to a rule: log impressions, not just clicks. If you only train on what got clicked, your training set is biased toward items the system already favored and contains no real negatives.

Second, leakage. Any feature that encodes information not available at prediction time, a value updated after the event, an aggregate computed over the future, will make offline metrics look great and fail in production. Features must be computed point-in-time-correct, which is again exactly what the offline feature store gives you.

Third, imbalance. Click-through and conversion problems have far more negatives than positives, and a naive model can score well by predicting the majority class while being useless. The fixes matter: negative downsampling with calibration correction, class weighting, and choosing metrics like precision-recall and calibration rather than raw accuracy. Just as important, keep the evaluation set at the true class distribution so you are not fooling yourself.

One more thing that separates people who have shipped from people who have studied: the train/test split for anything time-dependent should be by time, not random. You evaluate on the future the way the model will actually be used, not on a random slice that leaks tomorrow into today.

Candidate generation, then ranking

For recommendation, feed, and search, which is the most common ML design prompt by far, you cannot run a precise model over millions of items inside a latency budget. So the standard solution is two stages with opposite goals.

ml-system-deep diagram
Two-stage design: cheap high-recall candidate generation, then precise ranking on the shortlist.

Candidate generation optimizes recall and speed. From a catalog of millions, it produces a few hundred items that plausibly belong, using cheap methods: approximate nearest neighbor search over learned embeddings, retrieval from several sources like recent, popular, and similar-to-what-you-engaged-with, and lightweight rule-based filters. It is allowed to be imprecise, because the next stage sorts things out. What it must not do is drop the genuinely good items, because ranking can only reorder what generation hands it.

Ranking optimizes precision. It takes only those few hundred candidates, assembles a rich feature vector for each one, blending user, item, and context features, scores each with a heavier model, and orders them. Crucially, mature systems rank against a blended objective rather than a single click probability, because pure click optimization leads straight to clickbait. Some systems add a third re-ranking stage for business rules, diversity, and freshness.

The reason to volunteer this structure early is that it directly resolves the tension the interviewer is testing: how do you consider everything and still rank precisely inside a tight budget? You cut the millions down cheaply, then spend your compute only on the shortlist. This is the pattern documented publicly in YouTube's recommendation paper, and it shows up in some form across most large ranking systems.

Offline evaluation gates, online A/B decides

Offline evaluation and online testing answer different questions, and treating one as a substitute for the other is a classic mistake.

ml-system-deep diagram
Offline evaluation filters what you test; the online A/B test decides what you ship.

Offline evaluation, on a held-out set of logged data, tells you whether a model is promising. It is fast, cheap, repeatable, and safe, so you use it to filter many candidate models down to the one or two worth trying on real users. But offline metrics are computed on data the old system generated. You only observe outcomes for items the old system chose to show, so a better offline metric does not guarantee a better user outcome.

Online A/B testing answers the question that actually matters: does this model improve the business metric on live traffic? You route a fraction of users to the new model, hold the rest on the control, run long enough to reach statistical significance, and compare the online metric with proper attention to variance. You also watch guardrail metrics, so you do not celebrate a lift in clicks while quietly hurting retention.

Two rollout patterns bridge the gap safely. Shadow mode runs the new model in parallel without acting on its output, so you can compare predictions with zero risk. Gradual ramp-up limits the blast radius while you build confidence. The rule to state plainly is short: offline evaluation gates what you test, and only an online A/B test decides what you ship.

Serving: batch, online, and the latency budget

There are two ways to serve predictions, and the choice is a genuine trade-off, not a detail.

Batch inference precomputes predictions on a schedule and stores them for lookup. It is cheap, simple, and has no serving-time model latency, which makes it a fine fit when the input space is small and the prediction does not need to reflect the immediate request: daily product recommendations, precomputed user segments. Its weakness is staleness and the inability to react to real-time context.

Online inference computes the prediction on the request, so it reflects the current user, query, and session. The cost is a hard serving-time latency budget, a model that has to be small and fast enough to fit it, and infrastructure to fetch features quickly. Most feed and search ranking is online, because relevance depends on immediate context. In practice many systems compromise: they precompute the expensive parts, embeddings and candidate pools, in batch, and combine them with a light online model. You get freshness where it matters without paying the online cost everywhere.

The latency budget shapes everything upstream. It caps model size, limits how many features you can fetch and assemble, and it is the whole reason the online feature store is a low-latency key-value store rather than the warehouse. When you quote a latency number, frame it as the budget for the model step inside a larger request budget, not as a guarantee. Every added feature is a real tension here: it can lift model quality, but it costs time to fetch and assemble, and that time comes straight out of the ranking budget. Past a point, more features buy diminishing accuracy while eating latency you do not have.

Monitoring: an unwatched model rots in silence

An ML model is trained on a snapshot of the world, and the world moves. Every deployed model decays. The only questions are how fast, and whether you notice before your users do.

ml-system-deep diagram
Monitor three layers: input distributions, prediction distributions, and the business metric.

Data drift, also called covariate shift, is when the input distribution changes: new users, new items, a marketing campaign that shifts the traffic mix, so the model now sees inputs unlike its training data. Concept drift is when the relationship between inputs and the label changes: the same input now leads to a different outcome because of seasonality, a shift in taste, or a competitor's move. Both degrade quality even though your code never changed.

So monitoring has to watch three layers. Input feature distributions, to catch drift and broken pipelines feeding nulls or defaults. Prediction distributions, to catch the model's output shifting. And the downstream business metric, which is the ground truth but arrives late. Because labels are delayed, drift detection on inputs and predictions is your early warning, the thing that fires before the business metric visibly drops.

The mitigation is retraining on fresh data at a cadence matched to the drift rate. The interview-grade point is that retraining cadence is not a fixed schedule you pick arbitrarily. It is set by how fast your data actually drifts, which is precisely why you monitor rather than guess. Fast-moving signals like trending content may need hourly or streaming updates; stable relationships can be retrained weekly. Chip Huyen's writing on distribution shifts and monitoring lays this out in production terms, and it is worth reading before any senior ML interview.

Two failure modes deserve a special mention because they catch strong candidates off guard. Cold start is making good predictions with little or no history, and it comes in three flavors: new user, new item, and brand-new system, each of which pushes you toward content features, popularity fallbacks, and an exploration budget. And feedback loops are the quiet killer: a ranking system's own output becomes its next training data, so if it only shows what it already scores highly, it only ever learns about those items, and it narrows over time toward a shrinking set of popular content. The fix is to log impressions and non-clicks, reserve an exploration budget, and correct for position bias. Interviewers probe this because it separates people who see ML as a static prediction problem from people who understand a deployed ranking system is a closed loop that shapes the very data it learns from.

The patterns that transfer

Step back from recommendations specifically and the framework generalizes to almost any ML system design prompt.

ml-system-deep diagram
The transferable patterns: baseline first, separate your metrics, kill skew, evaluate then confirm, monitor for decay.

Start with a baseline before anything complex, so you have a bar to beat. Separate the offline metric you optimize from the online metric you care about, and never confuse a proxy win for a real one. Treat the feature store as the thing that guarantees train-serve consistency, because a feature computed two ways is a silent correctness bug, not a nicety. Use offline evaluation to filter and online A/B tests to decide. Serve within a budget, and let that budget discipline your model size and feature count. And monitor input, prediction, and business drift, because an unmonitored system degrades quietly until the metric everyone watches finally drops.

This is the consistent message across the most cited public sources on production ML. The Hidden Technical Debt in Machine Learning Systems paper is the canonical warning that model code is a tiny box in a much larger system, and that the surrounding infrastructure, data dependencies, feature management, configuration, monitoring, is where the cost and the risk concentrate. Google's Rules of Machine Learning opens by telling engineers to do ML like a good engineer, not like an ML researcher. Both point at the same conclusion the interview is testing for.

Which is the honest reason I keep coming back to the platform side. The model is the part you can swap in an afternoon. The parts that decide whether a system works on live traffic, feature stores, low-latency serving, drift monitoring, safe retraining, are the parts that take real engineering, and they are exactly what a senior interviewer probes hardest. Candidates who stand out treat the model as the easy part and the platform around it as the hard part, because in production that is precisely where the difficulty and the value live. Getting fluent in that platform layer is what turns a model that works in a notebook into a system that keeps working on live traffic, and it is the difference between a plausible interview answer and a production-ready one.

If you want to build that platform intuition properly, I teach ML systems and system design from first principles, with real diagrams and the trade-offs that only surface in production. The foundation lessons are free and need no signup at systemdesign.academy.

Top comments (0)