Interview guides · Bosch
Bosch Data Scientist Interview Questions & Guide 2026
Data scientist interview prep for Bosch: original practice on experiment design, SQL and metric reasoning, with worked solutions.
The 60-second brief
As a Data Scientist at Bosch, you operate at the intersection of heavy industrial engineering, IoT innovation, and cutting-edge machine learning. Your work directly drives the development of intelligent, scalable, and trustworthy AIoT solutions across diverse sectors such as automated driving, advanced driver assistance systems (ADAS), smart manufacturing, and connected mobility. By turning complex, high-dimensional sensor logs, audio, and image data into actionable intelligence, you help shape products that impact millions of users globally.
Product-sense cases reward reasoning from a mechanism to a testable prediction. Reciting every metric you can name reads as pattern matching; naming the single quantity that would move if your explanation were true reads as thinking.
Focus areas
- Size safety stock under variable lead times
- Price a service-level change in working capital
- Separate true demand from censored, stocked-out sales
Overview
This role is critical for transforming raw data from industrial machinery and connected vehicles into robust models that power the future of autonomous systems and Industry 4.0. You will collaborate closely with research scientists, hardware engineers, and product teams to bridge the gap between theoretical machine learning breakthroughs and production-grade deployments. Whether you are optimizing spatiotemporal models for connected vehicles or scaling deep learning pipelines for smart manufacturing, your insights will validate technical decisions and steer business strategy.
Expect an environment that values deep technical rigor, cross-functional collaboration, and continuous innovation. While tackling complex engineering hurdles, you will also be expected to maintain a sharp product and business focus, ensuring that every model or metric you build directly serves user needs and operational goals. Success here requires a blend of advanced statistical intuition, pristine coding practices, and the ability to articulate complex technical findings to non-technical stakeholders across the organization.
Where to focus your preparation
Treat the sections below as preparation areas and confirm the format with your recruiter.
Preparation focus
No round sequence has been reported for this company, so work the categories below and confirm the format with your recruiter.
What to demonstrate
- Breadth across SQL, experimentation and product reasoning
- Ability to state assumptions before choosing a method
How to prepare
- Drill the practice exercises below and time yourself
- Prepare three quantified stories about decisions you drove
Where candidates lose points
Attributing demand variability to the node where it is observed
Order variance amplifies as it moves upstream: batching to a truckload, minimum order quantities, forecast-driven ordering and promotional pull all convert smooth end demand into lumpy replenishment orders, so a plant can see a coefficient of variation several times that of the underlying consumption. Diagnosing the plant's schedule instability as a plant problem then produces interventions that cannot work, because the generating process sits one or two echelons downstream. Measure the bullwhip ratio explicitly (variance of orders placed by a node over variance of demand it received) at each echelon, and fix the ordering rule at the node where the ratio jumps rather than the node where the pain is felt.
Treating shipped units as demand
Shipments are censored at available inventory: on a stockout day the recorded quantity is a supply ceiling, not customer intent, and orders that were never placed because the item showed as unavailable leave no row at all. A forecast fitted on that history learns the constraint, under-forecasts the fast movers that stock out most often, and produces the replenishment that causes the next stockout, so the error compounds in one direction rather than averaging out. The fix is to model demand_qty rather than shipped_qty, flag stockout days with stockout_flag and treat them as censored (fit with a censored likelihood, or estimate unconstrained demand from uncensored periods and comparable locations), and to report how much of the history was censored alongside any accuracy number.
Reporting a p-value with no effect size or interval
Give the estimated difference with a confidence interval in the units the business cares about, then say whether that whole interval is worth acting on. A p-value only addresses whether you can rule out exactly zero; it says nothing about magnitude.
Interpreting a change before checking data quality and logging
Spend the first pass on row volume by day, null rates, duplicate keys, and whether the step change lands on a release or tracking-migration date. A discontinuity that coincides with a deploy is an instrumentation hypothesis before it is a behavioural one.
Questions & practice
Audit a daily inventory snapshot for silent corruption
Easy · data quality · invariants · completeness
You receive fct_inventory_daily with inventory_date, sku_id, location_id, on_hand_qty, allocated_qty, blocked_qty, available_qty, in_transit_qty, demand_qty, shipped_qty, stockout_flag and standard_cost_cents. The table is supposed to carry one row per active sku-location per date, including days with no movement. Write a check suite that returns one row per named check with the number of sku-location-days affected, the share of the scope, and the on-hand value at standard cost sitting behind the failures. Do not repair anything; the deliverable is the evidence.
Approach
- Start with the arithmetic identity the table declares: available_qty must equal on_hand_qty minus allocated_qty minus blocked_qty. Report exact row counts rather than a boolean, because a handful of violations is a feed bug and a uniform offset is a definition change upstream.
- Check sign constraints separately from the identity. Negative on_hand_qty usually means receipts posted out of order, while negative available_qty is legitimate at some sites when allocation is allowed to over-commit, so flag it and ask rather than assuming corruption.
- Check calendar completeness per sku-location by comparing the observed row count against the number of dates between that pair's first and last appearance. Count the missing dates without reindexing the frame, because filling them with zeros converts a feed gap into a plausible run of zero-demand days.
- Check stockout_flag in one direction only: available_qty of 0 at the cut-off with stockout_flag false is a contradiction, while flag true with positive available_qty is not, since the flag records an intraday touch of zero that a late receipt can recover.
- Weight every failure by on_hand_qty times standard_cost_cents so the summary orders checks by money at risk rather than by row count, and state the scope denominator on each row.
Follow-up
- Someone proposes asserting shipped_qty is at most demand_qty on the same row. Why does that fire on thousands of healthy rows?
- Half the missing dates fall on Sundays at one set of nodes. What is the most likely explanation and does it change the severity?
- Which of these checks would you run as a blocking gate before a nightly planning job, and which as a monitored report?
Recover unconstrained demand from stockout-censored history
Hard · censoring · maximum likelihood · em algorithm
A legacy extract has only inventory_date, sku_id, location_id, shipped_qty and stockout_flag; demand_qty was not populated before a cutover date. On a stockout day, shipped_qty is a lower bound on that day's demand. Model daily demand per sku-location as Poisson and fit its mean by maximum likelihood, treating stockout days as right-censored observations. Return the fitted mean per cell alongside the naive mean of shipped_qty and the censored share. Then validate against the post-cutover window where demand_qty exists.
Approach
- Write the likelihood before any code. Uncensored days contribute the Poisson pmf at the observed count; stockout days contribute the survival probability P(X >= y), because all you learned is that demand was at least what you managed to ship.
- Solve it as an EM fixed point rather than reaching for a general optimiser: the censored MLE equals the complete-data mean with each censored observation replaced by its conditional expectation, so iterate lambda_next = (sum of uncensored y + sum of E[X | X >= y, lambda]) / n until it stops moving.
- Use the closed form for the conditional expectation rather than truncating an infinite sum: for a Poisson, sum over k >= y of k*p(k) equals lambda times P(X >= y-1), so E[X | X >= y] = lambda * P(X >= y-1) / P(X >= y) for y >= 1. That removes the tail-truncation error entirely.
- Refuse to fit cells with too little signal. A sku-location with three non-zero days or with every day censored has no identifiable mean; return the naive figure with a flag rather than a confident number.
- Validate on the post-cutover window where demand_qty is populated: fit the estimator on shipped_qty and stockout_flag alone, and compare both the censored estimate and the naive mean against the true mean of demand_qty.
Worked solution (45 min)
- Split each cell's days into censored (stockout_flag true) and uncensored, and record the censored share.
- Initialise lambda at the mean of shipped_qty over all days, which is a strict lower bound on the answer.
- Iterate the EM update using scipy.stats.poisson.sf for the survival terms, stopping when the change in lambda falls below 1e-8 or after 500 iterations.
- Assemble a per-cell frame with lambda_hat, naive_mean, censored_share, n_days and a converged flag; mark thin cells rather than fitting them.
- On the post-cutover window, compute the true mean of demand_qty per cell and report the absolute error of lambda_hat against the absolute error of naive_mean.
Expected result: Per-cell lambda_hat that is greater than or equal to the naive mean of shipped_qty in every cell, with equality exactly when the cell has no censored days. The uplift grows with censored share. On the validation window, lambda_hat has lower mean absolute error against the true demand_qty mean than the naive figure does.
Verify it yourself
- Assert lambda_hat >= mean(shipped_qty) for every cell; the EM fixed point guarantees this because E[X | X >= y] >= y, so any violation is an implementation bug.
- Re-solve one cell by directly minimising the negative log-likelihood with a one-dimensional optimiser and confirm it agrees with the EM answer to at least six decimal places.
- Simulate a cell with known lambda, censor it artificially at a known threshold, and confirm the estimator recovers lambda within Monte Carlo error while the naive mean does not.
- Confirm cells with zero censored days return lambda_hat exactly equal to the sample mean, since the likelihood reduces to the ordinary Poisson case.
Follow-up
- The fitted mean is 18 percent above the naive mean for A-class items and 2 percent above for C-class. Why would you expect that ordering?
- The residual variance is three times the fitted mean. What does that break and what distribution would you move to?
- A stockout is often caused by a demand spike that day. What does that do to your estimate and can you correct it?
Simulate service levels under a variable inbound lead time
Medium · safety stock · monte carlo · service level
Daily demand for one SKU at one node is Poisson with mean 40. Replenishment lead time is 7 days with probability 0.7, 10 days with 0.2, and 14 days with 0.1, drawn independently per order. The policy is continuous review: order Q = 400 whenever the inventory position drops to the reorder point. Size safety stock two ways for a nominal 95 percent target, once as z times sigma_D times sqrt(mean lead time) and once with the variable-lead-time term. Simulate both and report achieved cycle service level and achieved unit fill rate.
Approach
- Compute both safety stock numbers analytically before simulating, so the simulation is a check on arithmetic you already understand rather than the source of the answer.
- Track inventory position (on hand plus on order) for the reorder trigger and on hand separately for the stockout test. Triggering off on hand alone re-orders while stock is already in transit and silently changes the policy you are measuring.
- Define the two outcomes precisely and separately: cycle service level is the fraction of replenishment cycles containing at least one unit of unmet demand, while fill rate is total units shipped from stock over total units demanded. They answer different questions and z targets only the first.
- Before running anything, bound the achievable service level by hand from the lead-time mixture. Each lead-time branch is a separate Poisson demand, so cycle service level is the probability-weighted sum of P(Poisson(40 x L) <= reorder point) across the three branches, and a reorder point that cannot cover the 14-day branch caps the policy at 0.9 no matter how the simulation is tuned.
- Run enough cycles that Monte Carlo error is small against the gap you are trying to see. The standard error of a service level is sqrt(p*(1-p)/n_cycles), about 0.005 at p = 0.7 with 10,000 cycles, so the 20-point gap between the two policies is unambiguous and a 1-point one is not.
- Let unmet demand be lost rather than backordered, state that choice, and note that switching to full backordering raises measured fill rate for the same policy.
Follow-up
- With Q = 100 against lead-time demand of 332 units, three or four orders are open at once. What happens to the meaning of a replenishment cycle, and to each of the two service measures?
- Lead time and demand are correlated because the supplier is capacity constrained in peak weeks. What does that do to the formula you used?
- How would you convert the extra 120 units of safety stock into an annual cost the business can weigh against the service gain?
As-of inventory position behind each short-shipped line
Medium · as-of join · window functions · lateral join
For every fct_order_line with line_status in ('shipped_short','backordered','cancelled_no_supply') and requested_ship_date in the last quarter, attach the inventory state that governed it: the fct_inventory_daily row for the same sku_id and ship_from_location_id with the greatest inventory_date strictly before requested_ship_date. Snapshots are taken at the location-local end of day. Return the line, ordered_qty, shipped_qty, and that snapshot's available_qty, blocked_qty, on_order_qty and in_transit_qty, plus the snapshot's age in days. Lines with no prior snapshot must appear with NULLs rather than disappearing from the result.
Approach
- Recognise the join is an inequality, not an equality. The snapshot is an end-of-day state, so the position that governed allocation is the last close strictly before the requested ship date, and the same-date row reflects the outcome rather than the cause.
- Implement it with LEFT JOIN LATERAL (SELECT ... WHERE sku_id and location_id match AND inventory_date < requested_ship_date ORDER BY inventory_date DESC LIMIT 1) ON TRUE, or equivalently ROW_NUMBER() OVER (PARTITION BY order_line_id ORDER BY inventory_date DESC) = 1 over a bounded candidate set.
- Bound the lateral with a floor such as inventory_date >= requested_ship_date - 14 so the scan does not walk the whole history for each line, and let that floor produce NULLs rather than silently dropping the line.
- Keep the join LEFT. Lines at a node with no prior snapshot are a data-quality finding worth counting, and an INNER join converts them into an invisible bias toward nodes with clean snapshot coverage.
- Check the row count before and after the join: the output must have exactly one row per order_line_id, and any excess means the as-of match is returning more than one candidate.
Worked solution (30 min)
- Filter fct_order_line to the three statuses and the quarter, and record the row count as the target.
- Attach LEFT JOIN LATERAL over fct_inventory_daily with the strict inequality, the fourteen-day floor, ORDER BY inventory_date DESC and LIMIT 1.
- Project the four quantity columns plus snapshot_age_days = requested_ship_date - inventory_date.
- Compare the result row count with the target; investigate any difference before aggregating anything.
- Count and group the NULL-snapshot rows by ship_from_location_id to see whether the gap is a node or a SKU launch artefact.
Expected result: Exactly one row per qualifying order_line_id, with snapshot columns drawn from the greatest inventory_date strictly less than requested_ship_date, snapshot_age_days at least 1, and NULL snapshot columns where no prior row exists inside the floor.
Verify it yourself
- COUNT() of the result equals COUNT() of the filtered order-line set. Any excess is fan-out from a non-unique as-of match.
- MAX(inventory_date) per line is strictly less than that line's requested_ship_date, with no equality cases.
- The count of NULL-snapshot rows is small and attributable to specific nodes or newly launched SKUs rather than spread evenly.
Follow-up
- Split the output by short_reason_code. Which codes should show available_qty at or near zero, and what does it mean when 'no_stock' lines show healthy availability?
- blocked_qty is large on many of these lines. Is that a planning problem, and who owns it?
- How would you extend this to the position at the moment of allocation rather than the previous close, and what would you need that the daily snapshot does not give you?
Lag-7 forecast accuracy and bias at weekly grain
Easy · forecast accuracy · null handling · aggregation grain
fct_inventory_daily has one row per sku_id x location_id x inventory_date carrying demand_qty, forecast_qty_lag7 (the forecast for that date as published seven days earlier, NULL before the series existed) and stockout_flag. Compute trailing eight-week WMAPE and signed weighted bias at the sku x location x week grain the ordering decision uses: aggregate demand and forecast to the week first, then form errors on the weekly totals. Exclude any week containing a NULL forecast day and report how many cell-weeks that removed. Return one accuracy row per ABC class.
Approach
- Roll daily rows to sku-location-week with SUM(demand_qty) and SUM(forecast_qty_lag7), carrying COUNT(*) FILTER (WHERE forecast_qty_lag7 IS NULL) so a partial week is visible rather than quietly summing to an artificially low forecast.
- Drop cell-weeks with any NULL forecast day and emit the dropped count as a column: an accuracy figure without its exclusion count cannot be checked by anyone.
- WMAPE = SUM(ABS(weekly_demand - weekly_forecast)) / NULLIF(SUM(weekly_demand), 0). Bias = SUM(weekly_forecast - weekly_demand) / NULLIF(SUM(weekly_demand), 0), signed, with cancellation as the whole point of reporting it next to WMAPE.
- Join dim_sku for abc_class and group there by re-summing both sides. Averaging per-SKU WMAPE gives a number weighted by nothing in particular.
- Report the share of retained cell-weeks containing a stockout day beside the result, because demand_qty on those days is censored at what could be supplied and the error is being scored against a truncated actual.
Follow-up
- Why is MAPE unusable on a C-class item at a forward-stocking location, and what do you score it with instead?
- WMAPE improves sharply when you move from sku-location-week to sku-region-week. Which of the two belongs in the planning review, and why?
- Bias is +6 percent and WMAPE is 45 percent. What does that pair tell you to investigate first?
Walk through how you would define success metrics for an explainable AI dashboard used by plant engineers.
Medium · product sense and metrics
Approach
- Decompose the metric into the rates that drive it, and say which one you would check first.
- Fix the population and the time window before naming any metric.
- Restate the decision this analysis has to support, and who acts on the answer.
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 would you design a core product metric to evaluate the performance of an autonomous driver assistance system in real-time?
Medium · product sense and metrics
Approach
- State what result would change your recommendation, so the answer is falsifiable.
- Name one primary metric, then the guardrail that stops it being gamed.
- Decompose the metric into the rates that drive it, and say which one you would check first.
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 would you measure the success of a new predictive maintenance feature deployed across our smart manufacturing shop floors?
Medium · product sense and metrics
Approach
- Decompose the metric into the rates that drive it, and say which one you would check first.
- 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.
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?
If we notice a sudden drop in daily active telemetry pings from our connected vehicle fleet, how would you systematically diagnose the root cause?
Medium
Approach
- Work from the decision backwards to the evidence you would need.
- 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
- How would you know your answer was wrong?
- What assumption would you test first?
A fill rate that improves by cancelling what it misses
Easy · gameable metrics · denominator integrity · audit series
Unit fill rate is defined as SUM(shipped_qty) over lines shipped on or before requested_ship_date, divided by SUM(ordered_qty) over lines with requested_ship_date in the week, excluding lines with line_status = 'cancelled_by_customer'. A node is now paid on it. Using fct_order_line (line_status, short_reason_code, ordered_qty, shipped_qty, cancelled_qty, substituted_sku_id, ordered_at_utc, requested_ship_date, account_id, sku_id, ship_from_location_id), list the routes by which this number rises without service improving, and specify the audit series that detects each.
Approach
- Attack the denominator first: removing a line removes a miss, and the only exclusion the definition grants is customer cancellation, a status written by the same operation being scored.
- Name re-entry: a short line closed and re-keyed as a fresh order arrives with a new requested_ship_date, so the miss leaves the scoring window entirely instead of being cancelled inside it.
- Name intake suppression: a line never created because the item showed unavailable enters neither side of the ratio, which is the only route that leaves no trace in this table and therefore needs demand-side evidence to detect.
- Name numerator inflation: substitution counted as a fill without saying so, partial shipments credited at ordered_qty, and shipping early against a requested date that was itself edited.
- Attach one audit series to each route from the same table: weekly cancelled_by_customer share by node, share of accounts re-ordering the same sku within seven days of a cancellation, substitution share, and median hours from ordered_at_utc to terminal status.
- Close with the structural fix: publish cancellation mix beside the rate, and pair it with perfect order rate, so that cancelling an order cannot improve both numbers at once.
Worked solution (20 min)
- Compute the weekly fill rate per node by re-summing shipped_qty and ordered_qty, never by averaging line-level ratios.
- Compute cancellation mix beside it: cancelled_qty split by line_status in ('cancelled_by_customer','cancelled_no_supply') as a share of ordered_qty, per node per week.
- Compute the re-entry series: lines whose (account_id, sku_id, ship_from_location_id) reappears within seven days after a cancellation or a short ship.
- Compute substitution share and median hours from ordered_at_utc to terminal status, both by node and week.
- Quantify the exposure algebraically: moving x units of unmet demand out of the denominator takes a rate r to r divided by (1 minus x/D), then read that against normal week-over-week variation.
Expected result: Four named routes, each with its audit series, plus the arithmetic that sizes the exposure: excluding one percent of the denominator lifts a 95.0 percent fill rate to 95.96 percent, which exceeds a typical week-over-week swing, so any monitoring threshold has to sit well below a one-point move. The recommendation is to publish cancellation mix and perfect order rate alongside the headline rather than to tighten the definition alone.
Verify it yourself
- The identity holds: denominator units equal shipped plus short plus backordered plus no-supply-cancelled units, with customer cancellations excluded and reported separately.
- Recomputing after relabelling a share of cancelled_no_supply units as cancelled_by_customer reproduces the r divided by (1 minus x/D) formula to rounding.
- A node improving genuinely shows a falling cancelled_no_supply share; a gamed one shows that share falling while cancelled_by_customer rises by a similar quantity in the same weeks.
Follow-up
- Which of these routes still works if you score lines rather than units?
- A node's cancelled_by_customer share doubled in one week. What confirms or clears it before you accuse anyone?
On-time rate improved the week the promise field changed
Medium · definition change · metric hygiene · release artefact
Customer on-time delivery jumped from 88 percent to 95 percent in one week and has stayed there. That week a release began writing re-confirmed dates into fct_order_line.promised_delivery_date, while original_promised_delivery_date still carries the first promise and both columns are populated for all history. Using fct_order_line (actual_delivery_at_utc, promised_delivery_date, original_promised_delivery_date, line_status) and dim_location.timezone, determine how much of the seven points is real. Deliverable: two numbers that sum to seven and one sentence of recommendation.
Approach
- Recompute the whole series twice on identical rows, once against promised_delivery_date and once against original_promised_delivery_date. Both columns exist for all history, so the counterfactual is free and the split is arithmetic rather than an estimate.
- Read the gap between the two series in the weeks before the release. If it was near zero and opens abruptly in the release week, the jump is the measurement changing. If the original-promise series also rises, that component is real and should be credited.
- Measure the mechanism directly rather than inferring it: by week, the share of lines where promised_delivery_date > original_promised_delivery_date and the mean slip in days. Any metric that can be satisfied by moving its own target is not measuring service.
- Handle the date-versus-timestamp comparison explicitly. actual_delivery_at_utc is a UTC instant while the promise is a local date, so convert using dim_location.timezone and compare against local end of day. Doing the comparison in UTC moves an entire timezone's deliveries across the boundary and invents a second, smaller step.
- Recommend the original-promise definition for the published metric and keep the re-promise series as a separate operational measure, stating that the two answer different questions rather than that one is simply wrong.
Follow-up
- Re-promises are legitimate when a customer agrees to the new date. How would you let those count without reopening the loophole?
- What automated check would catch the next definition change before it reaches a chart?
- Supplier inbound on-time has the same structure. Where is its equivalent loophole, and what does the metric tree already say about it?
Suggested practice checklist
Roughly 90 minutes a night on weekdays with one longer weekend block. The plan deliberately cuts scope rather than compressing everything, on the assumption that finishing one thing a night beats half-starting four.
Day 1 — Fix the scope and set a baseline
- Read the role description and write the three things the loop will almost certainly test, then write an explicit not-doing list for everything else and keep it visible all week.
- Take one 20-minute SQL prompt and one 10-minute metric question cold, and write the single sentence that says what blocked each attempt, since that sentence is what decides which two topics get the most evenings.
- Set the week's one rule: one problem finished to completion every night, including the night you only have 40 minutes.
Deliverable: A one-page scope with an explicit not-doing list and two cold attempts, each carrying one sentence on what blocked it.
Day 2 — One query pattern, written three times
- Choose the single pattern most likely to appear (a cohort retention grid, or a funnel counted by user) and write it three times from a blank file rather than editing the previous attempt.
- On the third attempt, write the grain of every CTE as a comment before writing its body.
- Stop at 90 minutes even if the third version is imperfect, and write the one thing you would fix with another hour.
Deliverable: Three independent versions of the same query plus a note on what changed between them.
Day 3 — Only the statistics you will be asked to defend
- Write, in under 200 words, how you would decide whether a difference between two groups is real: the test, its assumptions, and what you would switch to when an assumption fails.
- Compute a 95 percent confidence interval for a difference in proportions by hand on realistic numbers, then write in one sentence what changes if the two samples are paired rather than independent.
- Write your answer to "what does a p-value mean", check it against a definition, and delete the version that describes it as the probability the hypothesis is true.
Deliverable: A 200-word written answer and one hand-computed interval you can reproduce under pressure.
Day 4 — One case, and the assumptions holding it up
- Answer one product case aloud in 20 minutes with a recording running, then listen back with a pen and mark every claim you asserted without saying what it rested on: an assumed user behaviour, an assumed data source, an assumed baseline rate, an assumed grain.
- Pick the three assumptions the recommendation actually depends on, write how you would check each one against data, and say which one being wrong would flip the recommendation rather than merely weaken it.
- Write the four-step structure you used onto a card small enough to hold in working memory when you are nervous.
Deliverable: One recording, three load-bearing assumptions each with a written check, and a four-step structure card.
Day 5 — Your own work, timed
- Write a 90-second version and a four-minute version of your main project, and time both out loud rather than reading them.
- Prepare answers to the two follow-ups that always come: what you would do differently, and how you knew it worked.
- Put one number in the first sentence and be able to say exactly where that number came from and what it excludes.
Deliverable: Two timed narratives with one defensible number in the opening line.
Day 6 — The one full rehearsal, in a longer weekend block
- Run a 60-minute mock covering query work, a case and a behavioural question in a single sitting with no breaks, because sustained attention is the thing evenings have not trained.
- Immediately afterwards, and before hearing any feedback, write the three moments you lost the thread.
- Spend the rest of the block only on those three moments, and on nothing you merely feel shaky about.
Deliverable: Mock notes naming three failure moments with a specific fix written under each.
Day 7 — Taper
- Write the 20-minute warm-up you will actually do on the morning of the interview: one query you can already write from a blank file, one metric you can define out loud, and nothing you have never seen before.
- Re-read only your own notes from this week, and open no new material.
- Write down the logistics: the tool you will be asked to work in, whether lookups are allowed, and the sentence you will use when you do not know something.
Deliverable: A one-page card holding the case structure, the project numbers, and the logistics.
Ownership when the result is inconvenient
Sometimes the honest read is that the initiative did not work, and the person who commissioned the analysis was hoping otherwise. Interviewers want to know whether you softened it. Prepare the case where you delivered an unwelcome result, how you presented the uncertainty without hiding behind it, and what the team did next.
Quantify your own impact on a safety stock change honestly
Hard · impact measurement · confounding · difference in differences
In March you re-sized safety stock at twelve regional DCs using the variable lead time formula. Unit fill rate at those nodes rose from 94.1 to 96.5 percent by June. In the same window a supplier that had been running 71 percent inbound on-time recovered to 93 percent, and Q2 volume is seasonally about 8 percent below Q1. Your manager asks for one sentence on impact for a performance review. Write the claim you are willing to defend under challenge, and explain how you bounded the portion attributable to your change.
Approach
- Refuse the naive claim first: the 2.4 point gross movement contains at least three generating processes, and attributing all of it is the sort of claim that collapses the moment someone plots the supplier's on-time series next to it.
- Build a comparison group from nodes that did not get the change, check that their pre-period fill rate moved in parallel with the treated nodes for at least two quarters before March, and estimate the difference in differences with variance clustered at the node, since twelve treated clusters is the effective sample size regardless of how many node-weeks there are.
- Strip the confounders you can measure directly rather than trusting the design alone: restrict to sku-location cells sourced from other suppliers to remove the recovery, and hold the sku mix fixed across periods so the seasonal volume drop does not enter through mix.
- Sanity-check the mechanism, not just the coefficient: if your change worked, the improvement should concentrate in cells whose reorder point rose and in short_reason_code = 'no_stock' lines, and should be absent where the policy did not move. If the gain is spread evenly, something else caused it.
- State the result as an interval with the confounders named, and state the cost side too: extra units held at the applicable cost of capital, so the claim is a net one rather than a service headline.
- Write the sentence so that it survives someone else re-running it, which usually means a smaller number than the gross movement and a named method.
Follow-up
- The comparison nodes are not parallel in the pre-period. What do you do next?
- Your bounded estimate is roughly half the gross movement. How do you present that to a manager who already told his boss the larger number?
Walk through an inventory analysis that turned out wrong
Medium · error postmortem · snapshot bias · inventory turns
Six months ago you published inventory turns by node using the month-end on_hand_qty snapshot from fct_inventory_daily as the denominator, and two DCs cut cover on the strength of it. A finance review later showed month-end is systematically the lowest on-hand point of the month, because shipments cluster before close, so your turns were overstated and days of supply understated. Tell the story: what you built, how the error surfaced, what it cost, what you corrected, and the control that now prevents this class of mistake rather than this specific instance.
Approach
- Give the facts in order and own the decision, not just the code: you chose the month-end snapshot because it was one row per sku-location and fast, and you did not check whether the sampling point was representative.
- Quantify the error rather than describing it: recompute the same window against the average of every daily snapshot and state the gap in turns and in days of supply, which in a network with close-period push typically runs ten to twenty percent.
- Separate the consequence from the mistake honestly: say what the two DCs did, whether service actually degraded, and if it did not, say so instead of inflating the damage to sound accountable.
- Describe the correction and the notification: who was told, how quickly, and whether the restated number changed the recommendation.
- Close on the generalised control: a denominator convention written into the metric definition, plus a row-count assertion at each join grain, because the same shape of error appears when a daily snapshot is joined to shipment events on date equality and one shipment with several legs fans the snapshot out.
Follow-up
- How did you decide whom to tell first, and how did you phrase it?
- What made you trust the month-end snapshot in the first place, and what would have caught it in review?
Tell a sponsor the effect cannot be measured in six weeks
Hard · power · selection bias · quasi experiments · saying no
A VP wants a read in six weeks on a forward-stocking policy now live at eight of forty nodes. Replenishment lead time on the affected lanes is five weeks, the eight nodes were chosen by the ops team because they were the worst performers, and the cross-node standard deviation of weekly fill rate is about 3 points. The VP has already told his leadership team that a number is coming. Tell him what you can and cannot deliver in six weeks, and propose the design and timeline you would commit to instead.
Approach
- Do the power arithmetic in front of him rather than asserting the test is underpowered: comparing eight treated against thirty-two untreated node means with a between-node standard deviation of 3 points gives a standard error near 3 times the square root of one eighth plus one thirty-second, about 1.2 points, so the minimum detectable effect at 80 percent power and a two-sided 5 percent test is roughly 3.3 points. Any real effect smaller than that comes back as a null you cannot interpret.
- Name the burn-in problem separately: with a five-week lead time, six weeks covers barely one replenishment cycle, so whatever you measure is the transition rather than the new steady state, and the transition usually looks worse than the policy is.
- Name the selection problem third: nodes picked because they were worst will improve toward the network mean without any policy, so a simple before-and-after at those nodes is biased upward and will over-claim.
- Offer what is genuinely deliverable in six weeks: an implementation read, meaning whether the policy is actually in force at the eight nodes, whether inventory positions moved as designed, and whether any leading indicator such as short_reason_code mix is moving, framed explicitly as operational verification and not an effect estimate.
- Propose the real design with dates: extend to sixteen weeks covering roughly three cycles, use a difference in differences against matched comparison nodes chosen on pre-period fill rate and volume, cluster variance at the node, and pre-register the burn-in window that will be excluded.
- Help him with the commitment he already made: give him the exact wording for what he reports at week six, so the honest answer arrives as something he can say rather than as a refusal.
Follow-up
- He asks you to add the remaining thirty-two nodes to the rollout next month. What does that do to your design?
- If the effect really is 1 point, is the policy worth keeping, and how would you ever know?