cswork / libraryOpen practice workspace

Interview guides · Convoy

Convoy Data Scientist Interview Questions & Guide 2026

Practice explaining analysis before a Convoy data scientist interview: the recommendation, the uncertainty, the follow-ups.

The 60-second brief

As a Data Scientist at Convoy, you play a pivotal role in transforming the massive, complex world of digital freight networks into streamlined, efficient operations. This position sits at the intersection of advanced analytics, product strategy, and machine learning, directly influencing how shippers and carriers interact on the platform. You will tackle real-world logistical challenges—ranging from automated matching and dynamic pricing to routing optimization and network liquidity—by turning raw data into strategic direction.

A large share of questions open as "how would you measure X", where the real work is choosing the metric, fixing its denominator, and defining the population it applies to. Any computation comes last and is frequently not required at all.

Focus areas

  • Join daily snapshots to shipment events safely
  • Evaluate forecasts at the lag ordering actually uses
  • Price a service-level change in working capital

Overview

Your day-to-day impact involves designing rigorous experiments, developing core product metrics, and building analytical frameworks that guide business decisions across engineering, product, and operations teams. Because Convoy operates in a fast-paced and data-driven environment, your insights will directly shape product roadmaps and operational efficiencies. Success in this role requires a balance of heavy technical execution—particularly in data manipulation and experimentation—and a sharp product sense to identify where data science can unlock the most value.

This role suits professionals who thrive on ambiguity and enjoy solving messy, unstructured problems with high economic impact. You will be expected to take ownership of your problem spaces, communicate complex findings to non-technical stakeholders, and drive projects from conception to deployment. Expect a rigorous, fast-moving evaluation process that tests your technical depth and your ability to think critically about business metrics.

The Convoy interview process

Convoy candidates report 3 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.

Initial Screening

A screening call is a matching exercise run by someone who will not evaluate your statistics. They are checking that the work described on your resume is work you personally did, and that its scope matches the level the role is written for. Logistics get settled in the same half hour so nobody spends an interviewer's afternoon on a mismatch. The answer that fails is the one narrated in the plural. If every sentence is 'we built' and 'the team decided', there is nothing specific to write down about you. Name the piece that was yours, the decision you made inside it, and what changed after.

What to demonstrate

  • Whether the ownership implied by your resume survives one round of follow-up about who actually did which part
  • Whether your described scope (data size, stakeholders, what shipped) matches the seniority the role is written at
  • Whether timeline, location and compensation expectations make the rest of the loop worth scheduling

How to prepare

  • Rewrite your top three resume bullets in the first person singular, each with the decision you made and what moved afterwards, then say them out loud once so the 'we' does not return under pressure
  • Attach one number to each project: the baseline, the change, and the window it was measured over. Where impact was never measured, say that plainly rather than inventing a figure
  • Settle your compensation range before the call and give it as a range with a reason behind it, such as current total comp or a competing timeline, instead of deflecting the question twice

Phone Interviews

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.

Final On-site Interview

A loop is not scored one interview at a time. The people you meet compare notes afterwards, usually in a meeting you are not in, and the outcome turns on what each of them can say about you when asked. That rewards something other than survival: every room needs one specific thing worth repeating, and none of them can contradict another. The common way to lose is to tell the same project four times with different numbers in it, or to be uniformly fine in a way that leaves nobody with anything to argue for.

What to demonstrate

  • Whether your account of a project survives being told twice, with the same scale, the same metric definition and the same numbers each time
  • Whether each interviewer leaves with one concrete claim they could make on your behalf later, rather than an absence of complaints
  • Whether a question you already answered in an earlier room gets the same answer at the same depth, without visible impatience

How to prepare

  • Write a one-page fact sheet for your two or three main projects that fixes the numbers you will quote: rows of data, the metric as a single sentence, the effect you measured and how long the work took. Say them aloud from the sheet until they come out identical every time
  • For each kind of room you expect, decide the one sentence you want that interviewer repeating in a debrief, then check during the mock that you said it outright instead of implying it
  • Rehearse answering the same project question twice in one sitting, the second time as though you had not just answered it, because the thing that needs fixing is the flatness that creeps into a repeated story

Where candidates lose points

Computing average inventory from period-end snapshots

Shipments cluster before period close, so the month-end on-hand position is systematically the lowest point of the month; turns computed against it are biased high and days of supply biased low, frequently by ten to twenty percent, and the bias grows precisely when close-period push is strongest. The same shape of error appears when a daily snapshot is joined to shipment events on date equality: a SKU with several legs on one day fans the snapshot out and multiplies the valued inventory. Average across every daily snapshot in the window for the denominator, and join snapshots to events with an explicit as-of condition and a row-count check at each grain before aggregating.

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.

Reporting a mean for a heavy-tailed metric without saying what it hides

For spend, session length or items per order, a small fraction of units carries most of the total, so the mean has a wide standard error and one account can move it. Fix the handling before you see the result: cap or winsorise at a pre-declared percentile, and report the median or the share above a threshold next to the mean. Capping changes the estimand, so say which question the capped number answers, and check how much of any difference comes from the top 0.1 percent of units.

Explaining an aggregate move without decomposing the mix shift

Split the change in the aggregate into within-segment movement and movement in segment weights before you explain it. Every segment's rate can fall while the overall rate rises, purely because volume shifted toward segments that already had higher rates.

Questions & practice

Explain false positives and false negatives in the context of fraud detection on a logistics platform.

Medium · statistics and probability

Approach

  1. Say what the estimate is of, and over what population it generalises.
  2. Sanity-check the answer against a simple bound or a simulated case.
  3. Quantify uncertainty explicitly rather than reporting a point estimate alone.

Follow-up

  • Which assumption here is most likely to be violated in practice?
  • How would you explain this result to someone who does not know statistics?

When would you choose a simpler logistic regression over a complex tree-based model for predicting shipment delays?

Medium · machine learning and modelling

Approach

  1. Say how the offline result would be validated online before it is trusted.
  2. Frame the prediction: the label, the moment of prediction, and the action it triggers.
  3. Set a baseline first, so any model has something honest to beat.

Follow-up

  • Where could label leakage enter this setup?
  • How would you choose the decision threshold, and who owns that choice?

Measure demand amplification hop by hop up the network

Hard · bullwhip · hierarchy traversal · variance

Using dim_location (location_id, parent_location_id, echelon, location_type) and fct_shipment_leg (leg_id, shipment_id, origin_location_id, destination_location_id, direction, tendered_at_utc, shipped_units), quantify how order variability grows upstream. fct_shipment_leg carries no sku_id and no link back to order lines, so shipped_units is the node's whole mixed-SKU flow and the measurement is node-level by construction. For each node compute weekly units flowing out (what it served downstream) and weekly units flowing in (what it ordered up), then the ratio of their variances on detrended, deseasonalised residuals. Walk parent_location_id from a store to echelon 0 and report the ratio at each hop, naming the hop where amplification is introduced. dim_location has no path column; build the chain yourself.

Approach

  1. Date orders by tendered_at_utc, not delivered_at_utc. Tender is the closest observable proxy for the moment the ordering decision was made; dating by delivery shifts the series by transit time and smears the variance you are trying to measure.
  2. Build both series on the same calendar weeks and in the same units. Variance scales with the aggregation window, so a ratio formed from daily inbound against weekly outbound measures the calendar, not the ordering rule. The units are mixed-SKU counts because the leg table carries no sku_id, so a node whose product mix drifts toward smaller or larger pack sizes moves both series for reasons unrelated to its ordering rule; print that caveat next to the number rather than implying a per-SKU result.
  3. Detrend and deseasonalise before taking variances, or compute the ratio on residuals from a simple weekly seasonal baseline. A growing node otherwise scores as amplifying, when all you have measured is its trend.
  4. Walk the parent chain iteratively: start from the store rows, join dim_location to itself on parent_location_id, and repeat until parent is null, capping the loop at the known echelon depth and asserting the path length matches the echelon difference so a data cycle raises rather than hangs.
  5. Read the output as a sequence, not a set of numbers. A pass-through node such as a cross-dock should sit near 1.0, and the hop where the ratio jumps is where a batching rule, a minimum order quantity or truckload rounding lives. That is the node to fix, not the node that is complaining.

Worked solution (45 min)

  1. Assign an ISO week from tendered_at_utc and build two weekly series per node from fct_shipment_leg alone: outbound units summed where origin_location_id is the node, inbound units summed where destination_location_id is the node. No SKU filter is applied because the table has no sku_id, so both series are total unit flow.
  2. Regress each series on a linear trend plus week-of-year dummies, or subtract a centred moving average, and keep the residuals.
  3. Compute the amplification ratio per node as var(inbound residuals) / var(outbound residuals) over the shared weeks, requiring a minimum of 26 weeks before reporting a ratio.
  4. Build the parent chain from a chosen store by iteratively joining dim_location on parent_location_id until parent_location_id is null, asserting the loop terminates within the echelon depth.
  5. Emit the chain in order with echelon, location_type, both variances, the ratio, the week count and the mixed-SKU caveat, and mark the hop with the largest increase.

Expected result: An ordered table from store to echelon 0, one row per hop, each with the two residual variances, the ratio, the number of weeks it rests on, and a stated caveat that units are pooled across SKUs. Cross-dock and pass-through nodes sit near 1.0; at least one hop should sit materially above 1.0 and that hop is the finding.

Verify it yourself

  • Mass balance at a pass-through node: over a long window total inbound units should track total outbound units to within scrap, adjustments and the change in stock held. A persistent one-sided gap usually means one direction of leg is missing from the filter. Where fct_inventory_daily is available, sharpen this by comparing inbound minus outbound against the change in that node's on_hand_qty summed across SKUs.
  • Assert the parent walk terminates, contains no repeated location_id, and produces a path length equal to the echelon difference between the endpoints.
  • Construct a synthetic node that passes every unit straight through with no batching and confirm the ratio comes out at 1.0.
  • Recompute both variances after re-aggregating to 4-week buckets: the ratio should stay close while the individual variances grow, since the ratio is the scale-free quantity. Do not push this past the point where only a few dozen buckets remain, where the variance estimates themselves become too noisy to compare.

Follow-up

  • The ratio at one hop is 4.2 and the node insists it orders exactly to forecast. What ordering rules would produce that number anyway?
  • What would it take to run this for a single SKU family rather than total units, given fct_shipment_leg carries neither a sku_id nor any link to order lines, and which hops would still be unmeasurable after you added that link?
  • What would you expect this measurement to look like during a promotion, and does that change your conclusion?

Optimize a slow-running query that joins multiple large transaction tables across a distributed database.

Medium · sql and data manipulation

Approach

  1. Check whether any join is one-to-many before aggregating, or the sums inflate.
  2. Compute rates by summing numerator and denominator separately, never by averaging rates.
  3. Say which table is the grain you start from, and join outward from it.

Follow-up

  • How would you verify this result without re-running the same query?
  • How does the query change if the join becomes one-to-many?

Given a table of carrier bids and accepted loads, write a query to find the top three carriers by volume for each month.

Medium · sql and data manipulation

Approach

  1. State the window function and its partition and ordering out loud before writing it.
  2. Compute rates by summing numerator and denominator separately, never by averaging rates.
  3. Check whether any join is one-to-many before aggregating, or the sums inflate.

Follow-up

  • What breaks if events arrive late or out of order?
  • How would you verify this result without re-running the same query?

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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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)

  1. Filter fct_order_line to the three statuses and the quarter, and record the row count as the target.
  2. Attach LEFT JOIN LATERAL over fct_inventory_daily with the strict inequality, the fourteen-day floor, ORDER BY inventory_date DESC and LIMIT 1.
  3. Project the four quantity columns plus snapshot_age_days = requested_ship_date - inventory_date.
  4. Compare the result row count with the target; investigate any difference before aggregating anything.
  5. 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?

What key metrics would you track to measure the health and liquidity of a freight marketplace?

Medium · product sense and metrics

Approach

  1. Name one primary metric, then the guardrail that stops it being gamed.
  2. Restate the decision this analysis has to support, and who acts on the answer.
  3. Decompose the metric into the rates that drive it, and say which one you would check first.

Follow-up

  • Which segment would you cut first, and what would that rule out?
  • What would you do if the primary metric and the guardrail moved in opposite directions?

Extract retention cohorts from user activity logs using advanced aggregation and conditional logic.

Medium · product sense and metrics

Approach

  1. State what result would change your recommendation, so the answer is falsifiable.
  2. Decompose the metric into the rates that drive it, and say which one you would check first.
  3. Name one primary metric, then the guardrail that stops it being gamed.

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 new feature to improve shipper retention on the platform?

Medium · product sense and metrics

Approach

  1. Fix the population and the time window before naming any metric.
  2. State what result would change your recommendation, so the answer is falsifiable.
  3. 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?
  • Which segment would you cut first, and what would that rule out?

How would you define a primary success metric for an automated pricing recommendation engine?

Medium · product sense and metrics

Approach

  1. Name one primary metric, then the guardrail that stops it being gamed.
  2. Restate the decision this analysis has to support, and who acts on the answer.
  3. Fix the population and the time window before naming any metric.

Follow-up

  • Which segment would you cut first, and what would that rule out?
  • What would you do if the primary metric and the guardrail moved in opposite directions?

A test shows a statistically significant increase in conversion rate, but overall revenue decreases. How do you analyze and resolve this contradiction?

Medium · a/b testing and experimentation

Approach

  1. Name the randomisation unit first; it decides the variance and what the test can detect.
  2. Name the guardrails that would stop a launch even on a positive primary result.
  3. State the primary metric and the minimum effect worth shipping, then size the test.

Follow-up

  • What would you do if you could not randomise at all?
  • How would you handle interference between treated and control units?

How do you determine sample size and power when dealing with highly skewed shipment values?

Medium · a/b testing and experimentation

Approach

  1. Name the randomisation unit first; it decides the variance and what the test can detect.
  2. Decide the analysis before seeing data, including how long it runs and when you look.
  3. State the primary metric and the minimum effect worth shipping, then size the test.

Follow-up

  • How would you handle interference between treated and control units?
  • What would you do if you could not randomise at all?

Measure the demand that never becomes an order line

Hard · censored demand · proxy bias · unobservable metrics

Commercial asks for lost sales by SKU and node. fct_order_line records short-shipped lines (short_reason_code = 'no_stock') and no-supply cancellations, and fct_inventory_daily carries demand_qty, available_qty and stockout_flag, but an order a customer never placed because the item showed unavailable leaves no row anywhere. Define the metric you will publish, the proxy it rests on, the direction and likely size of its bias, and the guardrail that stops the proxy being quoted as a measurement.

Approach

  1. Separate observable from unobservable in writing. Short-shipped units with short_reason_code = 'no_stock' and cancelled_qty on lines with line_status = 'cancelled_no_supply' are recorded demand that went unmet. Demand that never became a line is absent from the schema at every grain, so no query returns it and no join recovers it.
  2. Publish the observable part under its own name, unmet recorded demand, and refuse to call it lost sales, because the two quantities differ by exactly the amount nobody can see.
  3. Build the proxy from uncensored periods: per sku-location, estimate a baseline demand rate from days where stockout_flag is false and available_qty stayed comfortably above that day's demand, adjust for day of week and season, impute the censored days, and take the excess over recorded demand.
  4. State the bias and its direction. The estimate is a lower bound, because purchases diverted before an order was keyed and demand absorbed by substitution onto another SKU are both invisible. The shortfall is largest on the SKUs with the most stockout days, so it correlates with the quantity being measured and cannot be treated as noise that averages out.
  5. Bound the size instead of asserting it: report the censored share of sku-location-days, and run the imputation on a holdout of uncensored days that you censor artificially, so the recovery rate is measured on data where the truth is known.
  6. Put the guardrail on use rather than on the number: any spend justified by this metric must still hold when restated on the observable part alone, otherwise the proxy is carrying the argument and should be labelled as doing so.

Worked solution (40 min)

  1. Quantify the censoring: share of sku-location-days with stockout_flag true, and share of ordered units on lines with short_reason_code = 'no_stock' or line_status = 'cancelled_no_supply'.
  2. Compute the observable metric: unmet recorded demand in units and at unit_price_cents, weekly by node and ABC class.
  3. Fit the baseline rate on uncensored days only, with day-of-week and week-of-year terms, pooled within ABC/XYZ class where a sku-location series is too thin to fit alone.
  4. Impute the censored days, take the gap, then hold out a random sample of uncensored days, censor them artificially at plausible availability levels, and measure what fraction of known demand the method recovers.
  5. Publish both series with the censored share and one written sentence naming what the proxy cannot see.

Expected result: Two published series rather than one: unmet recorded demand, which is computable and exact, and estimated unconstrained demand, which is modelled and is a lower bound. The bias statement records that the gap understates true demand because pre-order diversion and substitution are invisible, and that the understatement is largest on high-stockout SKUs, so the metric is least reliable precisely where it is most consequential. The holdout recovery rate is quoted as the only empirical evidence for the imputation.

Verify it yourself

  • Estimated unconstrained demand is at least recorded demand on every sku-location-day; a cell below it means the baseline was fitted on censored days.
  • The artificial-censoring holdout recovers a stated fraction of known demand; recovery near 100 percent means the artificial censoring was milder than real stockouts and the test is not informative.
  • Excluding stockout days from the baseline fit changes the baseline; if the number does not move, the filter is not being applied.

Follow-up

  • substituted_sku_id records substitutions. How much of the gap does it close, and what does counting it break in the donor SKU's own demand history?
  • How do you use the imputed series in a forecast without letting the imputation feed its own next round?

Unit fill rate fell four points in one region

Easy · fill rate · segment cuts · mix shift

Weekly unit fill rate for one region fell from 96.1 percent to 92.0 percent over four weeks and has not recovered. Network fill rate is flat. You have fct_order_line (ordered_qty, shipped_qty, requested_ship_date, ship_from_location_id, sku_id, line_status, short_reason_code), dim_location (location_type, region_code, echelon) and dim_sku (abc_class, xyz_class, lifecycle_status). Produce the first four query cuts, say what each one rules in or out, and name the single most likely cause together with the evidence that would confirm it. Thirty minutes, SQL plus a short written argument.

Approach

  1. Rebuild the metric by summing shipped_qty and ordered_qty to region level and dividing once, rather than averaging per-SKU-location rates. An unweighted mean of cell rates moves with portfolio mix on its own, so if the drop does not survive re-summing there is nothing physical to diagnose.
  2. Cut by ship_from_location_id first. If one node carries the whole drop the mix of demand across nodes is not the story and the problem is local; if every node fell a little, the cause sits upstream in supply or forecast rather than in any warehouse.
  3. Decompose the region change over abc_class by xyz_class cells into within-cell, mix and interaction terms: delta R = SUM(w0 * (r1 - r0)) + SUM(r0 * (w1 - w0)) + SUM((w1 - w0) * (r1 - r0)), where w is a cell's share of the denominator and r is its rate. A dominant mix term means demand moved toward hard-to-serve intermittent items and no cell actually got worse.
  4. Group the lost units (ordered_qty minus shipped_qty) by short_reason_code. 'no_stock' points at planning, 'pick_shortage' and 'damage_on_pick' mean the stock was physically present and execution lost it, 'allocation_rule' means the units existed and were promised to someone else, and 'credit_hold' is not a supply chain failure at all.
  5. Only then cross the weekly series against the promotion calendar, against SKUs with lifecycle_status = 'pre_launch' cutting in, and against accounts placing their first order in the window. A step change starting in the same week as a promotion or a new-item onboarding is a demand-side event, not a degradation.

Follow-up

  • Fill rate is flat nationally but down in this region. What does that tell you about where the stock went, and how would you test it?
  • Most of the failed units carry short_reason_code = 'no_stock', yet on_hand_qty at the node stayed above reorder_point_qty all month. How is that possible?
  • Would you publish this rate weighted by units or by revenue, and which team gets a different answer from each?

Suggested practice checklist

Instead of guessing where the week should go, day one measures it under a fixed rubric and allocates the remaining hours in proportion to the gaps. The method is deliberately rigid: the allocation is written down before any studying starts and is not renegotiated when a topic turns out to be unpleasant.

Day 1 — Diagnostic, scored before you study anything

  • Sit a 100-minute timed diagnostic in four blocks: 30 minutes of SQL across three prompts, 25 minutes of short-answer statistics, 25 minutes on one modelling or case prompt, and 20 minutes delivering one behavioural story aloud.
  • Score each block from 0 to 3 on a fixed rubric where 3 is correct and fluent, 2 is correct but slow or prompted, 1 is partially correct, and 0 is stuck, grading the output rather than how the attempt felt.
  • Allocate the hours for days two to five roughly in proportion to 3 minus the score in each block, write the allocation down, and commit to not revising it midweek.

Deliverable: A scored rubric and a fixed hour allocation for the rest of the week.

Day 2 — Largest gap: find the boundary rather than the subject

  • Break the weakest area into five named sub-skills (for query work: grain control, window frames, date arithmetic, set logic with NULLs, and reading a query plan) and rate each one, so the rest of the week targets a sub-skill instead of a subject.
  • Solve three problems chosen to sit just above where the rating drops off, and for each write the first move you failed to make.
  • Re-solve one of them from memory four hours later, on paper, with nothing open.

Deliverable: A five-item sub-skill map with the two blocking sub-skills circled.

Day 3 — Largest gap: drill the blocking sub-skill

  • Do eight short repetitions of the same shape rather than eight different problems, so what you practise is the pattern and not the puzzle.
  • Write the rule you now hold in one sentence, then test it against a case built to break it: a ranking function over a column with ties, or a two-sample test on observations that are obviously dependent.
  • Have someone else read your one-sentence rule and find the precondition you left out.

Deliverable: One rule statement with its preconditions attached and one counterexample that would have caught the incomplete version.

Day 4 — Second gap, plus maintenance on your strongest area

  • Run the same sub-skill map and boundary protocol on the second-largest gap, compressed into half the day.
  • Spend 25 timed minutes on your strongest area to stop it decaying, choosing the hardest problem you can still finish rather than an easy warm-up.
  • Compare how the two areas fail: whether you lose time on recall, on setup, or on arithmetic, because the fix differs for each.

Deliverable: A second sub-skill map plus a one-line diagnosis of how each area fails you.

Day 5 — The gap that is not a skill

  • Record yourself answering one technical and one behavioural prompt, then count two things in the playback: how many seconds before your first clarifying question, and how many sentences you started without knowing where they ended.
  • Rewrite your three most-used stock phrases into shorter versions, and practise saying "I do not know, here is how I would find out" without softening it into a guess.
  • Deliver one answer again with a hard 90-second limit to force structure before detail.

Deliverable: Two recordings with a counted improvement in time-to-first-question.

Day 6 — Retest under day-one conditions

  • Sit the same 100-minute diagnostic structure with new prompts of comparable difficulty and score it on the identical rubric.
  • Compare block by block, and for any block that did not move, change the method rather than adding hours: a block stuck at 1 usually means the practice was too varied, not too short.
  • Write which single block you would still lose the offer on.

Deliverable: A second scored rubric placed next to the first, with one named remaining risk.

Day 7 — Full loop under interview conditions

  • Run a 60-minute mock covering the two blocks that moved least, with an interviewer instructed to interrupt and change direction.
  • Write your recovery script for the moment you go blank: restate the question, state your assumption, name the first thing you would check.
  • Reduce the week to the rule statements you wrote, each with its preconditions attached, then say every one of them out loud without reading it and cut any you cannot state in a single sentence, since a rule you have to reconstruct mid-answer will not survive being interrupted.

Deliverable: A one-page card holding the recovery script and only the rules you could state from memory.

Being wrong in public

A number you shipped turned out to be wrong, and someone had already acted on it. That is one of the most useful stories a data person can carry. What is being scored is how fast you noticed, who you told first, and what you changed in the process so the same class of error could not repeat quietly.

Tell me about a time you had to push back on a product manager's feature request using data.

Medium · behavioural and stakeholder questions

Approach

  1. Pick a story where you drove the decision, not one where you observed it.
  2. Name the disagreement or constraint, and how you resolved it with evidence.
  3. Quantify the outcome, including what you would not claim credit for.

Follow-up

  • What did you decide not to do, and why?
  • How did you know the outcome was caused by your change?

Scope a vague request about rising inventory

Easy · scoping · stakeholder management · inventory turns

A planning director opens with: inventory is up twelve percent on flat shipments, get me an analysis by Friday. You have fct_inventory_daily (inventory_date, sku_id, location_id, on_hand_qty, standard_cost_cents) and fct_order_line (shipped_qty, unit_cogs_cents, requested_ship_date). Nothing else is specified: not the window, not the comparison basis, not whether the twelve percent is units or value. State the three questions you would ask before writing any SQL, name the decision each answer changes, and describe the first cut you would run if nobody answers you before Friday.

Approach

  1. Ask what decision hangs on the answer: a buy stop, a write-off provision, a policy review and a board slide all need different cuts, and the director usually has one of them in mind.
  2. Pin the measurement before the cause: units or value, which two windows are being compared, and whether the denominator is average daily on-hand or a period-end snapshot, since a month-end denominator biases turns high by ten to twenty percent and can manufacture the whole movement.
  3. Ask which part of the network is in scope, because echelon matters: a build at echelon 2 ahead of a promotion and a build of blocked_qty at a plant are different problems with different owners.
  4. Commit to a default if no answer arrives: value at standard cost, averaged across every daily snapshot in both windows, cut by echelon, then by abc_class and xyz_class, then by lifecycle_status to separate phase_out stock from active cover.
  5. Say out loud what the first cut cannot settle, so the director is not surprised: it localises the build but does not attribute it to forecast bias, a lot-size change or a supplier pulling orders in.

Follow-up

  • The build is concentrated in one product family at two DCs. What are your next two queries, and what would make you stop calling it a planning problem?
  • The director wants the number by Friday and the cause by Friday. Which do you drop, and how do you say so?

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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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?