Interview guides · Archer Daniels Midland
Archer Daniels Midland Data Scientist Interview Questions & Guide 2026
Data scientist prep for Archer Daniels Midland: practice defining a streaming and media metric, picking its guardrails and defending the tradeoff.
The 60-second brief
The role of a Data Scientist at Archer Daniels Midland is pivotal to leveraging data-driven insights that inform business decisions and optimize operations across the organization. In this role, you will analyze vast datasets to identify trends, build predictive models, and provide actionable insights that directly impact product quality, supply chain efficiency, and customer satisfaction. Given ADM's focus on sustainability and innovation, your contributions will not only enhance the company's business strategies but also support its mission to address global challenges in food and nutrition.
Allocate prep to your weakest link rather than your favourite topic. Of the three things that usually gate the outcome (SQL that is correct under messy joins, sound reasoning about experiments, and structured framing of an open-ended problem), candidates tend to over-invest in modelling theory and under-invest in framing.
Focus areas
- Split voluntary churn from involuntary payment failure
- Diagnose rebuffering by device, network and POP
- Correct discovery slates for position bias
Overview
As a Data Scientist, you will work closely with cross-functional teams, including engineering, operations, and product management. Your efforts will be integral in shaping products that meet market demands and drive business growth. This position offers the unique opportunity to engage with complex datasets and advanced analytical techniques, making it both challenging and rewarding. Candidates can expect to work on exciting projects that influence not just ADM's business trajectory, but also have a lasting impact on the agricultural sector.
The Archer Daniels Midland interview process
Archer Daniels Midland candidates report 3 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
Phone Screening
Whoever runs this call is usually not a practitioner. They take notes, and a hiring manager skims those notes later, so the real question is whether your work survives being written down by someone outside the field. Test every project sentence against that: could a non-specialist repeat it correctly without knowing what a propensity score is? Carry a plain-language version of each project and one reason you want this particular role that you could not copy onto another application. Vagueness at this stage reads as inexperience, even when the underlying work was genuinely deep.
What to demonstrate
- Whether a non-specialist can restate your projects accurately, since their paraphrase is what reaches the hiring manager
- Whether your reason for wanting the role points at the work itself rather than the company's reputation
- Whether your language signals the level being screened for: what you decided yourself versus what you were handed
How to prepare
- Write a two-sentence, jargon-free version of each major project: the question nobody could answer, and the decision your work changed. Read it to someone outside data and have them repeat it back
- Point your 'why this role' answer at something concrete in the job description or the product surface you would be working on, and keep it to two sentences
- Have two questions ready about measurement: which metric the team is held to, and who acts on an analysis once it lands
Interviews with Team Managers
An added round often puts you in front of someone outside the core hiring team: a partner engineer, a product owner, a domain expert, sometimes a more senior manager. The question they are really asking is not whether you can do the work but whether they would trust a number that came from you. That changes what a good answer looks like. Lead with what the decision cost and what it changed, keep the method available but not central, and be plain about the limits of your evidence. Overstating a result is the fastest way to lose this round.
What to demonstrate
- Whether you can explain a technical choice to someone who will never read your code, without either flattening it into nothing or hiding inside jargon
- Honesty about evidence strength: what the analysis establishes, what it only suggests, and what it cannot say at all
- How you take disagreement, specifically whether you update on a good objection, hold your position with reasons, or fold on contact
How to prepare
- Write the two-sentence version of your most technical project for a non-specialist, then check that neither sentence needs a method name to make sense.
- For one result you are proud of, write the strongest objection someone could raise and a response that concedes the part of it that is correct.
- Prepare one decision that turned out to be wrong: how you found out, what it cost, and what you changed afterwards. A senior cross-functional interviewer asks for this more often than a technical one does.
Technical Assessments
This round decides whether someone can hand you a schema and a question and trust the number that comes back. Correctness under a clock is the bar, not clever syntax. The habit that separates strong from weak answers is checking the grain: after every join, know how many rows you expect and whether the count moved. Most wrong answers in this format are not wrong logic, they are a fan-out from a key that turned out not to be unique, or a filter applied before an aggregate when it belonged after. Say what you expect before you run it.
What to demonstrate
- Whether your row counts survive each join, and whether you notice on your own when they do not
- Deliberate handling of rows that fail to match, including whether the question needs an inner join or a left join with the non-matches kept and counted
- Whether NULLs are treated on purpose, given that a NULL compares equal to nothing and that COUNT of a column skips it
- Reaching a defensible answer inside the window instead of a refined one after it
How to prepare
- Take a two-table schema, write a join that fans out on purpose, then fix it by collapsing the many-side to one row per key before joining. Repeat until the fix is reflex rather than recall.
- Write a funnel as one query and print the distinct user count at each stage, then confirm each stage is a subset of the one above it rather than assuming it
- Do a few timed runs in a plain text box with no autocomplete and no formatter, since assessment editors often have neither
Where candidates lose points
Counting plays without a qualification threshold, or changing the threshold without restating history.
Playback arrives as heartbeats, so a play only exists once you decide what counts, and the common 30-second convention is not a neutral analytics choice: in music it is also the boundary at which a play becomes payable, which makes the warehouse definition a payout definition. The threshold interacts violently with content length, so a catalogue of three-minute tracks and one of forty-minute episodes move in opposite directions when you change it, and a skip-heavy surface can add plays while adding no hours. Any metric mixing pre-threshold and post-threshold counts, or pooling short-form and long-form on a per-stream basis, moves by double digits for reasons that have nothing to do with the product.
Collapsing cancellation and payment failure into one churn number.
Involuntary churn from expired or declined payment instruments is a large and volatile share of gross churn, and it responds to retry schedules, card-updater coverage and billing provider, not to anything in the product. It also resolves late, so a period that looks involuntary today can be a successful retry next week, and reading the split before the dunning horizon closes overstates it. Compounding this, cancel-at-period-end means the cancellation request and the entitlement end are different timestamps on different rows, so a churn curve keyed on cancel_requested_ts and one keyed on churn_ts disagree by a full billing period.
Extrapolating a first-week lift inflated by novelty effects
Plot the treatment effect by days since first exposure instead of quoting one pooled average. A lift that decays toward zero across the test window is behaviour that will not persist, and annualising it produces a forecast that misses by an order of magnitude.
Stopping an experiment the moment it crosses significance
Fix the sample size or duration before launch, or use a method built for continuous monitoring such as a sequential test, always-valid confidence intervals, or group-sequential boundaries. Repeatedly checking a fixed-horizon p-value against 0.05 pushes the real false-positive rate well above 5 percent.
Questions & practice
What steps would you take to evaluate the success of a data model?
Medium · machine learning and modelling
Approach
- Say how the offline result would be validated online before it is trusted.
- Set a baseline first, so any model has something honest to beat.
- Check what information would not exist at prediction time, and exclude it.
Follow-up
- How would you choose the decision threshold, and who owns that choice?
- What would you monitor after launch to know the model is still valid?
Can you describe a project where you utilized machine learning?
Medium · machine learning and modelling
Approach
- Say how the offline result would be validated online before it is trusted.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Check what information would not exist at prediction time, and exclude it.
Follow-up
- Where could label leakage enter this setup?
- How would you choose the decision threshold, and who owns that choice?
Simulate concurrent-stream refusals on a shared family account
Medium · simulation · probability · queueing
A family account has four profiles and max_concurrent_streams = 2. Across an evening window of six hours, each profile independently attempts playback as a Poisson process at 0.75 attempts per hour. Durations are lognormal with a median of 24 minutes and sigma 0.6 on the log scale. An attempt arriving while two streams are already active is refused and abandoned, not retried or queued. Estimate the share of attempts refused and the mean refusals per account-evening, each with a 95 percent interval, then repeat with the cap at three.
Approach
- Simulate event-driven rather than on a time grid: draw exponential inter-arrivals per profile at rate 0.75 per hour, pool and sort the arrival times, and carry a short list of active end times.
- At each arrival, discard end times at or before that instant, then refuse if two remain. Only a served attempt draws a duration and pushes arrival plus duration; drawing a duration for a refused attempt and letting it hold a slot models a queue instead of a refusal.
- Start the window empty and do not warm it up, because the question is about an evening that begins with nobody streaming. Say explicitly that this makes the simulated share read below the steady-state value.
- Size the replications from a pilot: run 2,000 evenings, read the observed share, then solve 1.96 times the standard error to at most 0.002 using the between-evening standard deviation of the per-evening refusal share.
- Re-run with the cap at three by changing one constant and report the pair, because the decision this feeds is whether the cap is what the refusals are about.
Worked solution (30 min)
- Write one evening as a function: per profile, cumulative exponential draws with scale 1/0.75 hours truncated at 6 hours, then concatenate and sort the arrival times.
- Sweep arrivals in order against a list of active end times: pop the expired, refuse if the list is already at the cap, otherwise draw a lognormal duration with mean parameter log(24/60) and sigma 0.6 in hours and append arrival plus duration.
- Return (attempts, refusals) per evening; run a 2,000-evening pilot, take the per-evening refusal share, and size the full run from its standard deviation.
- Run the sized number of evenings at cap 2 and again at cap 3, with a fixed seed per configuration.
- Report the pooled share (total refusals over total attempts) with a clustered interval built from the per-evening shares, plus the mean and 90th percentile of refusals per evening.
Expected result: At cap 2, a refused share of roughly 0.25 to 0.30 and about four to five refusals per evening; at cap 3, roughly 0.10 to 0.13. Both sit just below the Erlang-B steady-state values for an offered load near 1.44 erlangs, which are 0.297 and 0.125.
Verify it yourself
- Erlang-B at a = 1.44 gives B(2) = (a squared over 2) divided by (1 + a + a squared over 2) = 0.297, and B(3) = 0.125. Lengthening the window from 6 to 48 hours should pull the simulation up toward these.
- Raising the cap to a large number drives refusals to exactly zero; setting it to zero refuses every attempt. Both are cheap wiring checks.
- Mean attempts per evening is 4 times 0.75 times 6, which is 18 within Monte Carlo error. Confirm the arrival process before trusting any refusal logic.
- The sampled mean duration is 24 times exp(0.6 squared over 2) = 28.7 minutes, not 24. A sampled mean of 24 means the lognormal was parameterised on the mean instead of the median.
Follow-up
- What changes if a refused attempt retries after two minutes instead of being abandoned?
- Erlang-B gives a closed form for this. Where does it agree with your simulation and where does it not?
- How would you find these refusals in fct_stream, given that a refused attempt produces no stream row at all?
Explain the difference between supervised and unsupervised learning.
Medium · sql and data manipulation
Approach
- State the window function and its partition and ordering out loud before writing it.
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
Follow-up
- What breaks if events arrive late or out of order?
- How would you verify this result without re-running the same query?
Write a function to calculate the mean of a list of numbers.
Medium · sql and data manipulation
Approach
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- State the window function and its partition and ordering out loud before writing it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
Follow-up
- How would you verify this result without re-running the same query?
- What breaks if events arrive late or out of order?
Pick one canonical version per work without losing remaster plays
Medium · deduplication · window functions · dimension grain
dim_content_version has content_version_id, content_id (stable across versions of the same work), title, content_type, duration_seconds, catalogue_added_ts, is_active_version and updated_at. A remaster, re-edit, dub or re-encode is a new row sharing content_id, and more than one row per content_id can carry is_active_version = true. Produce exactly one canonical row per content_id, preferring is_active_version = true, then the latest catalogue_added_ts, then the highest content_version_id as a deterministic tie-break. Then join fct_stream (content_version_id, played_seconds, is_qualified, started_at) and report qualified hours per content_id for last month.
Approach
- ROW_NUMBER() OVER (PARTITION BY content_id ORDER BY is_active_version DESC, catalogue_added_ts DESC NULLS LAST, content_version_id DESC), keeping rn = 1. The third sort key exists only so two runs return the same row; without it the winner among ties is whatever the engine happened to produce, and the result diffs against yesterday for no reason.
- Spell NULLS LAST out. In PostgreSQL, DESC defaults to NULLS FIRST, so a version with no catalogue_added_ts would win the canonical slot ahead of every dated one. Other engines order NULLs differently, which is exactly why the clause belongs in the query rather than in your head.
- Aggregate the streams first, at content_id grain, by joining fct_stream to dim_content_version on content_version_id and grouping on content_id. Every version's plays belong to the work.
- Only then attach the canonical attributes, with a join from the aggregate to the rn = 1 CTE on content_id. Inner-joining fct_stream to the canonical row instead discards every play of every non-canonical version, which is most of the catalogue's remasters and all of its dubs.
- Report the count of content_ids carrying more than one is_active_version row as a data-quality line beside the result, since that condition is what made the dedup necessary and its size decides whether this is a query fix or a pipeline fix.
Worked solution (25 min)
- Size the problem before solving it: count content_ids with more than one row, and separately those with more than one is_active_version = true row.
- Write the ROW_NUMBER CTE with explicit NULLS LAST, keep rn = 1, and assert COUNT(*) equals COUNT(DISTINCT content_id) in the dimension.
- Aggregate fct_stream to content_id through the version dimension, filtering is_qualified and last month, as SUM(played_seconds)/3600.
- Join the canonical attributes on and compare the grand total against the same aggregate computed at version grain.
Expected result: One row per content_id with at least one qualified stream last month, carrying title and duration from the canonical version and qualified_hours summed over all versions of the work. The grand total equals the ungrouped total over the same stream filter.
Verify it yourself
- COUNT(*) from the canonical CTE equals COUNT(DISTINCT content_id) in dim_content_version.
- Rerunning the CTE returns an identical set of content_version_ids, confirming the tie-break made it deterministic.
- Total qualified_hours matches the version-grain total to the second; any shortfall is the dedup-then-join bug.
Follow-up
- Which grain should hours be reported at, content_id or content_version_id, and who is the consumer of each?
- Rights expire per version, so one version's window can be closed while another is live. What does your canonical pick then mean for an availability report built on the same CTE?
Describe how you would approach a dataset with missing values.
Medium · product sense and metrics
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- State what result would change your recommendation, so the answer is falsifiable.
- Fix the population and the time window before naming any metric.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- How would you detect that the metric is being gamed rather than genuinely improving?
Can you walk us through a complex problem you solved using data analysis?
Medium · product sense and metrics
Approach
- Restate the decision this analysis has to support, and who acts on the answer.
- State what result would change your recommendation, so the answer is falsifiable.
- Name one primary metric, then the guardrail that stops it being gamed.
Follow-up
- Which segment would you cut first, and what would that rule out?
- How would you detect that the metric is being gamed rather than genuinely improving?
How would you communicate technical findings to a non-technical audience?
Medium · product sense and metrics
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- Fix the population and the time window before naming any metric.
- Decompose the metric into the rates that drive it, and say which one you would check first.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- How would you detect that the metric is being gamed rather than genuinely improving?
How do you prioritize tasks when managing multiple projects?
Medium · product sense and metrics
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- Restate the decision this analysis has to support, and who acts on the answer.
- Fix the population and the time window before naming any metric.
Follow-up
- How would you detect that the metric is being gamed rather than genuinely improving?
- What would you do if the primary metric and the guardrail moved in opposite directions?
How do you ensure the integrity of your data during analysis?
Medium
Approach
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
- Clarify what is being asked and what a complete answer would contain.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Define success before a startup-latency infrastructure change
Easy · metric design · quality metrics · guardrails · mix effects
An infrastructure change is expected to cut startup_latency_ms on tv_app playback. You must define success before the rollout. Available: fct_stream (startup_latency_ms, rebuffer_seconds, played_seconds, peak_bitrate_kbps, end_reason, start_source, device_type, cdn_pop, network_type). Propose one primary outcome metric, the latency statistic you will report and at which quantile, and two guardrails. State how you will stop a mix shift across device_type and cdn_pop from reading as an improvement, and name one way a latency win could be bought rather than earned.
Approach
- Separate the input from the outcome out loud: startup_latency_ms is the thing the change moves, but success is whether consumption improved, so the primary metric is qualified hours per active account-week on tv_app and latency is the mechanism metric that explains it.
- Choose the latency statistic for the shape of the distribution: startup latency is right-skewed with a long tail from cold caches and poor networks, so report p95 and p99 rather than a mean, because the mean moves with tail mass that a handful of streams contribute and the tail is where abandonment lives.
- Kill the mix effect by construction: compute the latency quantiles inside (device_type, cdn_pop, network_type) cells and aggregate with cell weights fixed from a pre-period, so that a rollout reaching wifi and well-provisioned points of presence first cannot show a win that is entirely composition.
- Guardrail one on how a latency win is bought: peak_bitrate_kbps and the rebuffer ratio, sum(rebuffer_seconds)/sum(played_seconds) with played_seconds = 0 rows excluded from both sides, because starting playback at a lower ladder rung lowers time to first frame and costs picture quality instead.
- Guardrail two on what the ratio hides: start-failure rate over streams with end_reason = 'playback_error' and played_seconds = 0, counted separately, since a point of presence that fails before first frame contributes to neither side of the rebuffer ratio and would otherwise report perfectly.
- State the exclusion: cut or exclude start_source = 'resume', because resumed playback starts from a warm buffer and a rollout that shifts the resume share moves pooled latency without any engineering change.
Worked solution (20 min)
- Write the primary metric with numerator, denominator and window, restricted to device_type = 'smart_tv' and its streaming-stick equivalents, and state that it is the outcome the change is judged on.
- Specify the latency readout: p95 and p99 of startup_latency_ms computed within (device_type, cdn_pop, network_type) cells, aggregated with pre-period cell weights, reported daily against the same cells pre-rollout.
- Construct one numerical counterexample showing the mix trap: two points of presence with unchanged within-cell latency but a shift in traffic share between them, and compute that the pooled mean moves while every cell is flat.
- Write the two guardrails: peak_bitrate_kbps distribution plus rebuffer ratio with the played_seconds = 0 exclusion stated, and start-failure rate over end_reason = 'playback_error'.
- State the exclusion rule for start_source = 'resume' and the reason, and write the one-line ship rule combining primary and guardrails.
Expected result: Primary: qualified hours per active account-week on TV devices. Mechanism metric: p95 and p99 startup_latency_ms within (device_type, cdn_pop, network_type) cells with fixed pre-period weights. Guardrails: peak_bitrate_kbps together with the rebuffer ratio excluding played_seconds = 0, and a separately counted start-failure rate over end_reason = 'playback_error'. The bought win is opening at a lower bitrate rung.
Verify it yourself
- The worked mix counterexample shows every cell flat while the pooled mean moves, which confirms the weighting is doing real work rather than being ceremony.
- Streams with played_seconds = 0 appear in exactly one metric, the start-failure rate, and in neither side of the rebuffer ratio.
- The bitrate guardrail is stated as a distribution, not a mean, so a shift of the low tail onto a lower ladder rung is visible.
- Resume-sourced streams are either excluded or reported as their own cut, so a change in resume share cannot move the headline latency.
Follow-up
- p99 falls but the mean rises. What do you conclude, and which cut would you look at first?
- The change only reaches accounts on app versions above a floor. How does that change what your comparison can claim?
- How large a latency improvement would you need before you expect qualified hours to move at all, and how would you size that before running it?
Weekly listening hours fell; check the calendar first
Easy · seasonality · data-completeness · metric-hygiene
A dashboard reports qualified hours per active account-week — sum(played_seconds)/3600 over fct_stream rows with is_qualified, divided by distinct (account_id, ISO week) pairs having a qualified stream — down 9% against the prior week. It is being read on a Wednesday and the current week is still open. Two public holidays fell inside the prior week. Using fct_stream (started_at, event_date, played_seconds, is_qualified, account_id, play_territory), establish whether anything real changed. Deliverable: a corrected comparison plus a written rule for how this chart is read from now on.
Approach
- Stop comparing an open week to a closed one. Either truncate the prior week at the same weekday the current week has reached, or exclude the open week entirely. A Wednesday read covers three of seven days and the four missing days include both weekend days.
- Establish the day-of-week profile before judging any week: qualified hours by ISO weekday across the last eight weeks. A truncated week is not a scaled-down full week, it is a systematically weekday-heavy one, and the ratio distorts in a specific direction — the numerator loses the two highest-hour days while the denominator only loses accounts who stream exclusively at weekends.
- Test partition completeness separately from seasonality. Recompute a day that closed two weeks ago and compare it against the value stored at the time. Offline playback uploads in bulk when the device reconnects, so a recent event_date keeps accruing for days; and if the pipeline stamps event_date at ingest rather than from started_at, those hours land on the wrong day entirely, which is a different defect with a different fix.
- Separate the holiday from a trend. Cut the prior week by play_territory and split territories that observe the holidays from those that do not, then recompute the week-over-week change on the non-observing set. A holiday that lifts consumption in two large markets raises the prior week's baseline, so the current week reads as a fall with no behaviour changing anywhere.
- Restate the comparison as complete-week against complete-week with the territory cut shown, and write the reading rule down: the current week is suppressed until it closes plus a stated late-arrival lag, and holiday weeks are annotated on the chart rather than explained in a thread each time.
Follow-up
- The holiday raised hours but also raised the active-account denominator. Which way does that push the ratio, and is the sign consistent with what you observed?
- What evidence sets the late-arrival lag, rather than picking a round number of days?
Suggested practice checklist
Four days spend equal time on query work, statistics, modelling and product judgement at deliberately shallow depth, which produces a scored map of where you actually stand. The last three days spend everything on the two areas the role weights most, and close by re-running day one to measure movement.
Day 1 — Breadth pass: query fluency
- Solve six prompts spanning aggregation, joins, window functions and date arithmetic in 60 minutes total, stopping at 10 minutes each whether or not it works, and mark every prompt as solved, solved slowly, or stuck.
- For each unsolved prompt write the single blocking sentence (I lost the grain, I did not know the frame clause, I could not express the date boundary) instead of reading the solution.
- Translate one pandas transformation you know well into SQL and one SQL query into pandas, checking that both return the same row count and the same totals.
Deliverable: A scored six-row table, one line per prompt, saved for the day-seven re-run.
Day 2 — Breadth pass: statistics and inference
- Answer ten short questions in writing with nothing open: what a p-value is conditional on, what a 95 percent interval covers across repeated samples, when a paired test is the right one, what the bootstrap estimates, why multiple comparisons inflate false positives, how controlling the family-wise error rate differs from controlling the false discovery rate, what power depends on, what a missed real effect costs a product, the three situations where the central limit theorem does not rescue you (small n, very heavy tails, dependent observations), and what a standard error is the standard deviation of.
- Grade yourself against a reference and count only the answers that were exactly right, not the ones that were nearly right.
- Rewrite the two weakest answers the following morning from memory in full sentences.
Deliverable: Ten graded answers with an honest count of exact hits.
Day 3 — Breadth pass: modelling
- Take one tabular dataset end to end in 90 minutes: a leakage-safe split, a baseline that is not a model (majority class or historical mean), one regularized linear model, one gradient-boosted tree, and a single evaluation metric chosen before you look at any result.
- Write why that metric fits the cost structure: precision at a fixed recall for alerting, calibration for anything feeding a price or a threshold, ranking metrics for retrieval, and note that area under the ROC curve is insensitive to class balance in a way that can flatter a rare-positive problem.
- Name the leak you were most likely to introduce (an encoding fit on all rows before splitting, or a feature computed after the label's timestamp) and write the check that would have caught it.
Deliverable: A notebook whose first cell states the metric and the baseline, plus two lines on what beat what and by how much.
Day 4 — Breadth pass: product judgement
- Answer three case prompts aloud at 15 minutes each, timing how long passes before you state a success metric.
- For one case write the first segmentation you would run and the row counts you expect per segment, so that a tiny segment cannot quietly drive the conclusion.
- Take a metric definition you did not write, from a public dashboard, a textbook, or documentation you already have open, and list every place two analysts implementing it would diverge: which rows the denominator admits, whether the unit is an account or a person, what the time window is anchored to, and what happens to data that arrives late. Then write the one question that would close the largest of those gaps.
Deliverable: Three recorded case answers plus an ambiguity list for a metric someone else defined, ending in the single question you would ask about it.
Day 5 — Depth, first area
- Rank the four areas by how many bullet points in the role description each one covers, pick the top one, and spend the entire day inside it.
- Work the six hardest problems you can find in that area and for each write the generalizable move you should have reached for first, rather than the answer.
- Re-solve the two you failed the same evening with notes closed.
Deliverable: Six generalizable moves written as instructions to yourself, not as solutions.
Day 6 — Depth, second area, and the seam between them
- Repeat the depth protocol on the second-ranked area with the same six-problem structure.
- Construct one problem that requires both areas at once, for example a metric redefinition whose effect you must validate with a test whose readout you then have to query.
- Solve your own combined problem end to end and note where the handoff between the two areas cost you time.
Deliverable: One combined problem, solved end to end, with the handoff failure written down.
Day 7 — Integration and re-measurement
- Re-run the six prompts from day one under the same clock and compare both correctness and time.
- Run a 60-minute mixed mock that moves between areas without warning, since switching cost is what breadth passes do not train.
- Write the two areas you would still fail on, and the sentence you will use in the interview when you hit one of them.
Deliverable: A before-and-after score table plus a written plan for the two remaining gaps.
The project you argued against
Saying no well is a senior skill and it is rarely rehearsed. Think of a time you told someone their analysis was not worth doing, or that the experiment could not answer their question at the sample size available. Explain what you offered instead. Refusal without an alternative reads as obstruction rather than judgement.
Describe a time when you had to advocate for a data-driven decision.
Medium · behavioural and stakeholder questions
Approach
- Close with what you would do differently, concretely.
- Quantify the outcome, including what you would not claim credit for.
- Pick a story where you drove the decision, not one where you observed it.
Follow-up
- What would you do differently if you ran that project again?
- What did you decide not to do, and why?
State the impact of your last year without inflation
Hard · self-assessment · attribution · counterfactual reasoning
You are asked what your work was worth over the last year. Two candidates are on the table. First: a dunning-schedule change you analysed, shipped in March with no holdout, after which the involuntary share of gross churn fell three points. Second: a metric-definition change you drove, which nobody can attribute revenue to. Deliverable: the impact claim you make for each, the counterfactual attached to each, and which one you lead with in a performance review — with the reason.
Approach
- The probe is whether you apply the same causal standard to your own work as to a product experiment. Attach the counterfactual before the claim: involuntary share of gross churn responds to card-updater coverage, billing_provider mix, retry schedules and the dunning horizon you read it at, any of which can move three points with the schedule change contributing nothing.
- Say which evidence would separate those, then say plainly which you actually have. A staggered rollout by billing_provider, a holdout, or at minimum a flat pre-period series would each support a different strength of claim; with none of them, the honest claim is a contribution to a favourable movement, stated as such.
- Check the classification itself before claiming the movement is real: the split between cancelled_voluntary and failed_involuntary must be computed only after the dunning horizon has closed for every period in the month, or retries still in flight are counted as churn and the share reads too involuntary in one direction and corrects in the other.
- Price your contribution rather than the outcome. The value of analysis that changed a decision is the decision's delta multiplied by the probability the decision would not have been taken without it, and being explicit about that second factor is most of what honesty means here.
- Make the definition-change claim concrete rather than apologetic: name the decisions that would have been taken on the wrong number, the reports it reconciled, the recurring argument it closed, with dates. Then lead with whichever claim survives questioning, not whichever carries the larger number, because an inflated first claim makes the second unbelievable.
Follow-up
- Your manager writes up the churn improvement and credits it to you. Do you correct it, and to whom?
- How would you have designed the March rollout so that attribution was possible, at what cost in delay?
- Name something you worked on last year that had no impact, and say what you learned from that rather than from the wins.
Walk through an analysis you shipped that was wrong
Medium · error ownership · data quality · postmortem
Describe a case where you delivered a result that was later shown to be wrong, and it had already been acted on. Cover how the error surfaced, whether you or someone else found it, what the wrong number caused, and what you changed afterwards. Prepare an example whose root cause was a definition, a denominator or a join — not a transcription slip. The interviewer will push on the mechanism, not the apology. Deliverable: a four-minute account that ends with a specific control now running in a pipeline.
Approach
- The probe is whether your account has a mechanism in it. Choose an error that generalises — a denominator that silently changed population, a join that fanned rows, a metric partitioned on event_date while offline playback arrived days late and landed in the wrong partition — rather than one that only teaches you to check your typing.
- State the blast radius factually and early: which decision was taken, how long the number stood, what it cost. A candidate who softens this is answering a different and easier question, and the interviewer can hear the substitution.
- Explain how it surfaced without adjusting who found it. The generalisable detail is why your own checks did not catch it, which is a statement about your checks rather than about your luck.
- Name the control you added and where it now lives: a row-count assertion after the fan-out join, a reconciliation that recomputes a closed day after late-arriving offline playback and alerts above a threshold, a denominator assertion inside the query. A fix that lives in a pipeline is different in kind from a resolution to be more careful.
- Close with whether the control has fired since, or how you tested that it would. That single sentence is what separates a fix from an intention, and interviewers ask for it when candidates do not offer it.
Follow-up
- Why didn't your own review catch it? Be specific about what you did check.
- What class of error would that control still not catch, and what would you add next?
- Have you found an error in someone else's published analysis since? How did you raise it?