Opens this plan in Hirezen, where one click makes it a position.
Machine Learning Engineer interview questionsCoding — the training-serving skew round
A 60 min interview plan with a time-boxed script, what each question is for, and the signals to score against. Key skills: Whether the candidate can find where a model's offline and online worlds disagree by reading code rather than by re-running the notebook: spotting a transform fitted on data it will never see again, a clock that moves between training and serving, a null filled two different ways, and a feature that quietly knows the label — then writing the parity test that would have caught all of it..
Two code paths that should agree
What this section is for
Purpose
Runs over a repository, not a whiteboard. Before the round, plant the disagreements yourself so you know exactly what is in the pack: `features.py` builds the training frame and fits a standard scaler on the whole frame before the eval split is taken; `serve.py` assembles the same features at request time and computes `days_since_last_order` from the wall clock where training used the snapshot date; the offline path fills a missing `avg_basket` with the column median and the serving path fills it with zero; a categorical is encoded against the training vocabulary and an unseen value at serving time maps to the first category instead of to unknown; and `refund_flag` is joined from a table whose rows are written after the label window closes. Leave one ordinary feature alone so there is something correct in the pack. Add a README line — "offline AUC 0.81; shadow-serving agreement with offline scores 71%" — and nothing else. Five plants at this density is about ten minutes of honest reading for someone who knows what they are looking for, so the 14 below is tight on purpose: the first question is scored on what the candidate reads first, not on how many they find. Book the room for 70 minutes; the closing exchange is not inside the 60.
I'm [YOUR_NAME] and I run the ML platform at [COMPANY_NAME]. This is a code-reading hour, not an algorithms hour — nothing in here needs a whiteboard. You are getting a small repository with a model that scores well offline and disagrees with itself in production, and I want to watch how you find out why.
What this section is for
Purpose
Re-aims a candidate who prepared for a data-structures round, so the first minutes are spent on the repository rather than on recalling the interview they expected.
Two files matter: the one that builds training features and the one that builds the same features when a request arrives. The README says offline AUC 0.81 and 71% agreement between offline scores and what shadow serving produced on the same customers. Read for a few minutes before you say anything. I would rather you were quiet and right than fast.
What this section is for
Purpose
Gives permission to read rather than perform, so silence is not penalised and the first thing said is a finding rather than a reflex.
Tell me what disagrees between these two paths. Not a fix yet — I want the list, in the order you would worry about it, and I want to know how you found each one.
What this question is for, and what to listen for
Purpose
Separates candidates who read the serving path against the training path line by line from candidates who read the training path and reason about what serving probably does. The whole discriminator is whether they compare or infer.
Signals to score
- Opens both files side by side and reads the serving path against the training path rather than reading one and inferring the other
- Names the scaler fitted before the split, and says which number it inflates — the offline AUC, not the serving score
- Names the wall-clock recency feature, and says its effect grows with the age of the training snapshot
- Names the two null-fill strategies and says what a customer with no basket history looks like to each path
- Names the unseen-category mapping and says which category it silently becomes
- Flags `refund_flag` as arriving after the label window and treats it as a different class of problem from the other four
- Orders the list by damage rather than by line number, and can say why
- Asks which of the five would show up as the 71% agreement figure and which would not, since a pure offline leak leaves shadow agreement intact
- Says out loud what is correct in the pack, not only what is wrong
Follow-up questions
- The scaler is fitted on the whole frame. Which reported number does that move — the offline AUC or the serving score — and does it explain the 71%?
- Of the five, which would you have caught with a unit test, and which needs data to see?
- Pick the one that costs the business the most on a normal Tuesday. Why that one?
- Is the refund flag the same kind of bug as the other four?
- If the shadow-agreement figure were 99% instead of 71%, which of these would you still expect to be in the code?
Prove it, then stop it happening again
What this section is for
Purpose
Moves from reading to writing. The candidate picks one skew and writes the test that demonstrates it, then generalises to the check that catches the class. The code is scored on whether it would run, not on style.
Pick the disagreement you would fix first and write me the test that fails today because of it. You can write it against the fixtures in the repo or invent a row — say which. Then we will talk about what makes it a class of test rather than a test.
What this section is for
Purpose
Sets the deliverable as a failing test rather than a fix, so the candidate has to reproduce before repairing and cannot hand back a patch whose effect nobody measured.
Write the parity test: take rows from the training frame, push each one through the serving path as if it were a request, and assert the features match. Make it fail on this repository, then tell me what it needs to pass for the right reasons.
What this question is for, and what to listen for
Purpose
The load-bearing exercise of the round. A parity test is the one instrument that catches this class before shadow serving does, and most engineers who have shipped a model have written one badly — with a float equality, a live clock, or a sample that never includes a null.
Signals to score
- Replays real training rows rather than synthetic ones, and says why the null and the unseen category have to be in the sample
- Freezes the clock in the test, or names that the test is flaky by construction until it does
- Compares floats with a tolerance and can say what tolerance and where it came from
- Asserts feature by feature and names the failing feature in the assertion message, rather than asserting on the final score
- Makes the test fail first, and reads the failure back before touching either path
- Fixes the disagreement in one place both paths share, or says explicitly why the two paths cannot share code here and what guards the seam instead
- Says how many rows the test should replay and how they should be chosen, with a reason
- Names where the test runs — on every change to either file, and again before a model is promoted — and what happens when it fails there
- Distinguishes a parity test from a skew monitor in production, and says which of the five plants only the monitor would catch
Follow-up questions
- You compared the two feature vectors with `==`. Will that pass tomorrow?
- The test replays a hundred rows and passes. None of them had a missing basket. Is the bug fixed?
- Where does this test run, and what does a failure block?
- You have made both paths call one function. What is the argument against that?
- The recency feature is right in the test and wrong in production a week later. What did the test not do?
The feature that knows the answer
What this section is for
Purpose
Two questions on the class of bug a parity test cannot see. The first is about time; the second is about what the fix costs and who has to be told.
`refund_flag` is joined from a table whose rows are written up to three weeks after the order. Training uses whatever is in the table today. Tell me what this feature actually measures in the training set, what it measures at serving time, and what the model has learned.
What this question is for, and what to listen for
Purpose
Tests whether the candidate reasons about when data becomes available rather than about what a column is called. This is the most expensive class of ML bug and the one least visible in code review.
Signals to score
- States that in training the flag is populated for orders that later refunded, and at serving time it is almost always false because the refund has not happened yet
- Names this as the feature encoding the label, or a near relative of it, rather than as a generic leak
- Predicts the direction of the damage: offline metrics too good, production scores systematically shifted for the segment the flag marks
- Reaches for a point-in-time join — reconstruct what each row's features were as of its prediction time — as the fix, and can say what it needs to exist
- Says the honest fix makes the offline number go down and that the lower number is the true one
- Asks how the label itself is defined and when it becomes known, since the same problem may be in the target
- Generalises: asks which other features in the frame come from tables that are written after the event
- Names a check that would catch the class — feature availability logged at serving time and compared with training
Follow-up questions
- Fix it properly. What happens to the offline AUC, and what do you tell the person who put 0.81 in a deck?
- Which other columns in this frame would you now go and check, and how?
- Is the label defined the same way in training and in the product?
- You cannot rebuild the history of that table. What do you do instead?
- Could a parity test have caught this?
You have found five things. You are one engineer and it is Wednesday. What do you fix this week, what do you fix this quarter, and what do you write down so the next model does not inherit any of it?
What this question is for, and what to listen for
Purpose
Attaches sequencing and ownership to the findings. A candidate who has done this work has an order and a reason; one who has read about it has a list.
Signals to score
- Puts the production-facing skews first and the offline-only inflation second, and says why in terms of who is affected
- Names the refund flag as the one whose fix needs a conversation before code, because it changes a number someone has already reported
- Proposes the parity test as the first thing shipped, before any fix, so each fix is measured
- Distinguishes what is fixed in this repository from what is fixed in the platform — a shared feature definition, a point-in-time store, an `as_of` convention
- Says what goes in the post-mortem and who reads it, and does not call it a post-mortem for a bug that had no incident
- Names the person who owns the model's number and tells them before the number moves
- Sets a check that runs on the next model, not only on this one
Follow-up questions
- Someone wants the recency fix shipped today without the test. Do you?
- Which of the five is a platform problem rather than a model problem?
- Who do you tell before the offline AUC changes, and what do you say?
- What would you want the next person who trains a model here to be unable to get wrong?
Last thing, and it is the part I weight most: what do you want to ask me about how models get from a notebook to a request here? I will answer anything — whether we have a feature store, who owns the training snapshot, what our parity coverage actually is.
What this section is for
Purpose
A candidate who has shipped a model asks about the seam between training and serving; one who has not asks about the model zoo. Naming the topics makes the signal about what they choose.
To close the loop honestly: [name one true, unflattering fact about your own training-serving seam — a feature computed two ways, a snapshot nobody can reproduce, a parity test that was never written]. If you take this job you inherit that. Better you knew now than in week three.
What this section is for
Purpose
Ends on a real, specific fact about the team's own pipeline. It is the strongest pitch available to the candidate this round exists to hire, and a deterrent to one who wanted the problem already solved. It only works if it is true — check before you say it.
Machine Learning Engineer interviews — common questions
- Who is this Machine Learning Engineer interview plan for?
- It is written for the interviewer, not the candidate: the hiring manager, engineer or panel member running the Coding — the training-serving skew round for a Machine Learning Engineer role. It gives you a 60 min script to follow in the conversation — 4 questions with what each one is for and the signals to score against — so you are not writing the round from scratch the night before.
- What does the Coding — the training-serving skew round assess?
- This round is focused on: Whether the candidate can find where a model's offline and online worlds disagree by reading code rather than by re-running the notebook: spotting a transform fitted on data it will never see again, a clock that moves between training and serving, a null filled two different ways, and a feature that quietly knows the label — then writing the parity test that would have caught all of it.. It works through Two code paths that should agree, Prove it, then stop it happening again and The feature that knows the answer, scoring against 33 observable signals, with follow-up prompts on all 4 questions for going deeper where an answer is thin.
- How is the 60 min split up?
- Two code paths that should agree (14 min), Prove it, then stop it happening again (24 min), The feature that knows the answer (22 min). The timings are there so the round stays on schedule and every candidate gets the same shape of interview — which is what makes two candidates comparable afterwards.
- What other rounds should I run for a Machine Learning Engineer?
A single round does not cover a whole role. The other rounds in this library for a Machine Learning Engineer: