cswork / libraryOpen practice workspace

Interview guides · Devoteam

Devoteam Data Scientist Interview Questions & Guide 2026

Case practice for Devoteam data scientist candidates: scope a vague prompt into a measurable question before you analyze it.

The 60-second brief

The role of a Data Scientist at Devoteam is pivotal in driving data-driven decision-making across various business functions. As a Data Scientist, you'll leverage advanced analytical techniques and machine learning algorithms to extract insights from complex datasets, ultimately influencing strategic directions and enhancing the user experience. Your work will directly impact product development, operational efficiency, and customer satisfaction, making your contributions essential to the success of Devoteam.

When randomisation is off the table, the skill being checked is naming an identification strategy together with the assumption it rests on: parallel trends for difference-in-differences, relevance and exclusion for an instrument, overlap and conditional ignorability for matching. Say the assumption out loud and say how you would try to break it.

Focus areas

  • Decompose a metric move by segment and mix
  • Separate novelty effects from durable behaviour change
  • Turn a vague request into a measurable question

Overview

In this dynamic environment, you will collaborate with cross-functional teams, including product managers, engineers, and business analysts, to tackle complex challenges. The scope of your work will encompass diverse projects, such as predictive modeling, data visualization, and A/B testing, allowing you to engage with innovative technologies and methodologies. This role not only offers the opportunity to work on high-impact projects but also to shape the future of data science practices within the company.

The Devoteam interview process

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

Screening Interview

Because the format is not fixed, prepare the reasoning rather than the ritual. Nearly every version of this round draws on the same underlying material: a design you can defend, a metric you can define exactly, an analysis whose assumptions you can state out loud. Only the wrapper changes, whether that is a take-home, a live case, a deep dive on past work, or a rough estimate on a whiteboard. Answers rehearsed to fit one shape stall the moment the shape differs. Practise naming the assumption behind a number, then saying how much the conclusion moves if that assumption is wrong.

What to demonstrate

  • Whether your justification for a method survives the question 'why not the simpler thing', including when the simpler thing would have worked
  • Precision under pressure: what exactly counts as an active user, a conversion or a success, over what window, with what exclusions
  • Whether you carry an argument through to a recommendation instead of stopping at a list of tradeoffs

How to prepare

  • For each project you plan to mention, write the metric definition in one sentence: numerator, denominator, time window, exclusions. Say it out loud once, because vagueness shows up in speech before it shows up on paper.
  • Rehearse the same project at three lengths: two minutes, ten minutes, and a deep dive on one technical decision. Cutting live is harder than it sounds.
  • For your headline result, write down what would have had to be true for it to be wrong, and how you ruled that out.

Technical Interview

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

Interviews with Team Leads

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.

Where candidates lose points

Comparing cohort retention curves of different maturities, or building the curve from users who are still present

A cohort four weeks old has no week-8 value, so an average taken across cohorts silently drops young cohorts from the later columns and keeps them in the earlier ones. The curve then bends upward at the tail, and the reading that 'retention is improving over time' is an artefact of which cohorts survived to be measured. The same error appears in the denominator when retention is computed over users active in the current period rather than over the full original cohort, which conditions on survival and guarantees a flattering number. The fix is a triangle: fix the cohort at signup, bound every window on both sides, and only compare cells where every cohort has had the full elapsed time, publishing the rest as blank rather than as a partial average.

Treating last-touch attribution as the causal value of a channel

The attribution label on dim_user is the output of a rule that assigns full credit to whichever touch happened to be recorded last inside a lookback window, and that rule systematically rewards channels that sit close to the conversion, especially branded search and retargeting, which largely intercept demand that already existed. Reallocating spend on those labels moves budget toward the channels that are best at being last, which is why attributed return on ad spend often improves while total signups do not. Nothing in the touchpoint data can settle this, because the counterfactual of not running the channel was never observed. The credible reads are a geo holdout or a scheduled pause, sized in advance on the total-signups metric rather than on the attributed one, and the honest framing in the meantime is that the label describes correlation with conversion and not incremental contribution.

Solving silently instead of narrating the reasoning

Say which branch you are taking and why you chose it over the alternative, for example checking the denominator first because it changes what the comparison means. A correct answer that arrives with no visible path scores below a rigorous one that needed a hint.

Ignoring interference between units in a marketplace experiment

Ask whether one unit's treatment can change another unit's outcome through shared inventory, a matching pool, a social graph or a common budget. Where it can, randomise at a level that contains the spillover, such as region or time slice, and say explicitly what that costs you in statistical power.

Questions & practice

Write a function to calculate the Pearson correlation coefficient between two lists.

Medium · statistics and probability

Approach

  1. Sanity-check the answer against a simple bound or a simulated case.
  2. Say what the estimate is of, and over what population it generalises.
  3. Translate the result into the decision it informs, in one plain sentence.

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?

How would you implement a decision tree from scratch?

Medium · machine learning and modelling

Approach

  1. Check what information would not exist at prediction time, and exclude it.
  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

  • 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?

Discuss the efficiency of different algorithms for sorting data.

Medium · machine learning and modelling

Approach

  1. Say how the offline result would be validated online before it is trusted.
  2. Check what information would not exist at prediction time, and exclude it.
  3. Pick an evaluation metric that matches the cost of each error type, not a default.

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?

Describe a project where you utilized machine learning techniques.

Medium · machine learning and modelling

Approach

  1. Frame the prediction: the label, the moment of prediction, and the action it triggers.
  2. Pick an evaluation metric that matches the cost of each error type, not a default.
  3. Set a baseline first, so any model has something honest to beat.

Follow-up

  • What would you monitor after launch to know the model is still valid?
  • Where could label leakage enter this setup?

Simulate the false positive cost of repeated peeking

Medium · simulation · peeking · type i error

Quantify the cost of peeking. Simulate a two-arm experiment with no true effect: each arm accumulates Bernoulli conversions at a base rate of 0.10 up to 40,000 units per arm. Run a two-sided two-proportion z-test at alpha 0.05 at ten equally spaced interim points, and record whether the test ever crossed. Report the false positive rate over at least 10,000 replications, alongside the rate for a single look at the final sample only. Use a fixed seed and report a Monte Carlo standard error on both figures.

Approach

  1. Generate each replication as two cumulative sums of Bernoulli draws, then read the interim points off the cumulative arrays. Regenerating data at each look would make the looks independent, which destroys exactly the dependence the exercise is about: later looks share data with earlier ones.
  2. Use the pooled-variance two-proportion z: p_pool = (x1+x2)/(n1+n2), z = (p1-p2) / sqrt(p_pool*(1-p_pool)*(1/n1 + 1/n2)), reject when |z| > 1.96. State that the normal approximation is fine here because the smallest look has roughly 400 expected conversions per arm.
  3. Vectorise across replications rather than looping: draw a (reps, n) array of uniforms, threshold at 0.10, cumsum along axis 1 and slice the ten look indices. A per-replication loop at 10,000 by 40,000 is unnecessarily slow.
  4. Record the any-cross indicator per replication, take the mean, and compute the Monte Carlo standard error as sqrt(p*(1-p)/reps) so the reported figure comes with its own precision.
  5. Report the single-look rate in the same run as a control. If it does not land near 0.05, the bug is in the test statistic and not in the peeking argument.

Worked solution (30 min)

  1. rng = np.random.default_rng(seed); for memory, batch the replications in chunks and accumulate the any-cross count across chunks.
  2. Per chunk: draw (chunk, 40000) uniforms per arm, x = (u < 0.10).cumsum(axis=1), slice columns at indices 3999, 7999, ..., 39999.
  3. Compute the ten z statistics vectorised over the chunk, take crossed = (np.abs(z) > 1.96).any(axis=1).
  4. Aggregate: peek_rate = total_crossed / reps; single_rate = mean of |z_final| > 1.96; mc_se = sqrt(p*(1-p)/reps) for each.

Expected result: The single-look rate lands at 0.05 within about 0.005 at 10,000 replications. The ten-look rate lands near 0.19, which with 10,000 replications has a Monte Carlo standard error of about 0.004, so anything in roughly 0.18 to 0.20 is consistent and anything near 0.40 indicates independent redraws.

Verify it yourself

  • The single-look control recovers 0.05 within two Monte Carlo standard errors; if it does not, the z statistic is wrong and the headline number is meaningless.
  • The crossing rate is monotone in the number of looks: 1 look near 0.05, 2 near 0.08, 5 near 0.14, 10 near 0.19.
  • Halving the base rate to 0.05 leaves the peeking rate essentially unchanged, since the result is about the test's random walk and not about the conversion level.
  • Re-running with the same seed reproduces the figure exactly.

Follow-up

  • Re-run with 40 looks instead of 10. Why does the curve flatten rather than continue rising linearly?
  • Among the replications that crossed, what is the mean observed lift, and why is it not zero?
  • What does an O'Brien-Fleming boundary or an always-valid confidence sequence change about this simulation, and what does each cost in power?

Attribute account MRR to first-touch channel without seat fan-out

Medium · fan-out · joins · revenue · attribution

dim_user holds user_id, account_id, first_touch_channel, account_created_at_utc. dim_account holds account_id, lifecycle_status. fct_subscription_period holds account_id, period_start_utc, period_end_utc, period_status, mrr_cents_constant_fx. For a given as-of date, report active MRR by the first-touch channel of the account's earliest-created user. An account has many users and many periods. The channel totals must sum exactly to total active MRR on that date, and accounts whose label is NULL must appear as their own bucket.

Approach

  1. Reduce the label side to one row per account before any join: ROW_NUMBER() OVER (PARTITION BY account_id ORDER BY account_created_at_utc, user_id) = 1 over dim_user, carrying first_touch_channel. Joining dim_user to the period table directly repeats each revenue row once per seat.
  2. Reduce the money side to one row per account too: the period where period_start_utc <= :as_of AND period_end_utc > :as_of AND period_status IN ('active','past_due'). If more than one row survives that filter the account holds overlapping subscriptions, which must be deduped or deliberately summed, and either way the choice is stated rather than left to the join.
  3. Join the two one-row-per-account CTEs and SUM(mrr_cents_constant_fx). Use the constant-FX column, since the same query run in two quarters otherwise reports currency moves as channel performance.
  4. Bucket NULL first_touch_channel as 'unattributed' with COALESCE instead of letting it drop. Roughly the share of users with no observed touch is not small, and dropping it understates the total and inflates every named channel's share.
  5. Reconcile: the SUM over the joined result must equal the SUM over the period CTE alone. That single equality check catches fan-out immediately, which is why it is worth writing before presenting the number.

Follow-up

  • Which user should own the account's label: earliest created, the 'owner' role, or the one who converted? What does each choice systematically favour?
  • What does this table entitle you to say about the value of a channel, and what does it not?
  • Some accounts have a parent_account_id. How does rolling those up change both the numerator and the channel mix?

Seven-day activation rate by weekly signup cohort

Easy · cohorts · activation · date-bounds

dim_user holds user_id, account_created_at_utc, is_internal. fct_event holds user_id, occurred_at_utc, is_core_action. A user is activated when core-action events fall on at least two distinct UTC dates inside [account_created_at_utc, account_created_at_utc + 7 days). Return, for the last twelve complete weekly signup cohorts, the cohort week, cohort size, activated users and the activation rate. Exclude is_internal users. Every signup in the cohort week stays in the denominator, including users who never returned.

Approach

  1. Start from dim_user as the denominator spine with is_internal = FALSE and DATE_TRUNC('week', account_created_at_utc) as the cohort key. Driving the query from the event table instead would silently condition on having events and delete the entire non-activating population.
  2. Join fct_event on user_id with is_core_action = TRUE and a per-user bound, occurred_at_utc >= u.account_created_at_utc AND occurred_at_utc < u.account_created_at_utc + interval '7 days'. The bound is correlated to each user's own signup timestamp, not a single global date range.
  3. Aggregate per user with COUNT(DISTINCT occurred_at_utc::date) >= 2, then LEFT JOIN that back onto the spine and COALESCE the flag to FALSE so non-activators contribute a zero rather than vanishing.
  4. Restrict the published cohorts to those whose week ended at least eight days ago. A cohort younger than that has not finished its seven-day window, so its rate is mechanically low and reads as a decline.
  5. Roll up by summing the numerator and denominator per cohort week, and state the two-distinct-days threshold next to the number since it is a choice that re-bases the whole history if changed.

Worked solution (20 min)

  1. Write the cohort spine and confirm its total equals the count of non-internal signups in the date range.
  2. Write the per-user distinct-active-days CTE with both interval bounds and inspect a handful of users manually.
  3. LEFT JOIN, COALESCE the flag, aggregate to cohort week.
  4. Apply the eight-day publication lag and drop the incomplete cohort.
  5. Re-run with a closed upper bound (<= +7 days) and note how many users change state, to show the boundary is doing work.

Expected result: Twelve rows, one per cohort week, each with cohort_size, activated and rate. Cohort sizes sum to the total non-internal signup count across those twelve weeks. No cohort is younger than eight days.

Verify it yourself

  • activated is never greater than cohort_size in any row.
  • A user with three core actions on a single day is not counted as activated.
  • Removing the LEFT JOIN in favour of an inner join raises every rate, which demonstrates the denominator was being conditioned on survival.
  • Cohort sizes sum to an independent COUNT(*) over dim_user for the same range.

Follow-up

  • Why two distinct days rather than one event? What happens to the published history if someone changes it to three?
  • Invited seats and SSO-provisioned users get an account_created_at_utc at provisioning and may never sign in. Should they be in this denominator?
  • The rate rose 3 points this week. What do you check before believing it?

Given a dataset, how would you approach a predictive modeling task?

Medium · product sense and metrics

Approach

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

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 prioritize tasks when faced with multiple data projects?

Medium · product sense and metrics

Approach

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

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?

Explain the difference between supervised and unsupervised learning.

Medium

Approach

  1. State your assumptions explicitly before working the problem.
  2. Work from the decision backwards to the evidence you would need.
  3. 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?

Metric tree for a seat-expansion push on seat-based plans

Medium · revenue · seats · leading indicators

Sales wants a push to add seats to existing accounts. Tables: dim_account (account_id, seats_licensed, seats_assigned, lifecycle_status, current_plan_tier), fct_subscription_period (subscription_id, account_id, mrr_cents_constant_fx, seats_billed, period_start_utc, period_end_utc, change_reason), and fct_event (is_core_action, user_id, account_id, occurred_at_utc). Build the metric tree from net revenue retention down to the metric the push team is graded on, name the primary, and give the guardrail that fires before the damage shows up in NRR. Deliverable: the tree, the primary metric, and the lead-time argument for the guardrail.

Approach

  1. Grade the team at the grain it controls. NRR is a trailing twelve-month revenue-weighted ratio that the push cannot move inside a quarter and that also moves for reasons the push does not touch, so it belongs at the top of the tree and nowhere near the target.
  2. Define the primary as a delta rather than a count: the sum of period-over-period mrr_cents_constant_fx changes on rows with change_reason = 'seat_change' and a positive seats_billed delta. A COUNT of seat_change rows rewards churn of seats as much as growth.
  3. Name the failure the target creates: seats sold and never assigned book revenue now and reappear as a seat reduction at the next renewal, six to twelve months later, comfortably outside the window the team is measured in.
  4. Pick licensed-seat utilisation as the guardrail precisely because of that lag — distinct user_id with an is_core_action event in the trailing 28 days over seats_licensed, MRR-weighted across lifecycle_status = 'active' accounts — and read it against each account's renewal date rather than the calendar.
  5. Close the horizon gap with a rule instead of a hope: the push books expansion MRR immediately but retains credit only for accounts still above the utilisation threshold at the following renewal.

Worked solution (30 min)

  1. Build the tree downward: NRR at twelve months, then expansion plus contraction plus churned MRR, then seat_change deltas and tier changes, then seats billed per account, then licensed-seat utilisation.
  2. Write the primary as a period-over-period MRR delta restricted to positive seat changes, in constant FX, on subscription_id.
  3. Write the guardrail with its weighting and its read points: 30 and 60 days before each account's renewal date.
  4. State the lead time in months: utilisation moves within one 28-day window of a seat sale, while the seat reduction it predicts reaches NRR only at the next renewal.
  5. Write the credit rule that ties the two horizons together.

Expected result: A tree with expansion MRR as the primary, utilisation as the guardrail with its lead time stated in months, and a credit rule that makes the push team carry the renewal-horizon consequence.

Verify it yourself

  • Summing mrr_cents_constant_fx across all period rows in a month double-counts any account with a mid-period change; the monthly figure must be built from period boundaries rather than a naive SUM over rows.
  • seats_assigned can exceed seats_licensed during a grace period, so a utilisation computed on assigned seats can exceed 1. The denominator is seats_licensed.
  • The MRR-weighted and unweighted utilisation means should differ substantially. If they do not, single-seat accounts are probably being dropped somewhere in the aggregation.

Follow-up

  • How do you separate seat expansion from price and tier expansion inside NRR without double-counting either?
  • An account buys 40 seats and assigns 6 during a phased rollout. Is that expansion, and what would change your answer?
  • What does the utilisation threshold do to a genuinely growing customer three weeks into a rollout?

Tell a pipeline outage from a collapse in usage

Medium · pipeline-failure · instrumentation · event-volume

Weekly active accounts completing a core action fell 9%, and almost the entire fall sits in accounts whose events carry surface = 'ios'. App crash rates and store reviews are unchanged. You have fct_event with occurred_at_utc, received_at_utc, event_name, is_core_action, app_version and surface, plus fct_session and the ingestion job run log. Establish within the hour whether iOS engagement fell or iOS events stopped arriving, name the evidence that distinguishes them, and say what you would publish on the dashboard in the meantime.

Approach

  1. Compare the event-name composition inside surface = 'ios' against the prior four weeks as shares, not counts. A behaviour collapse scales most event names together; a dropped event definition or a broken downstream filter hits specific event_name values while page_view and session-opening events hold steady. That shape difference is the fastest discriminator available.
  2. Profile the received_at_utc minus occurred_at_utc distribution per day for surface = 'ios'. A stalled-then-backfilling pipeline shows a fat upper tail and a recovering p99; a silently dropped stream shows an unchanged lag distribution over a smaller volume. The two failure modes have different remedies and different histories.
  3. Cut by app_version. A logging SDK change arrives with one build and ramps with its adoption curve; an infrastructure fault arrives across every build within the same hour. Checking this costs one group-by and rules out half the hypothesis space.
  4. Cross-check against a signal that does not travel the suspect path: server-emitted events with session_id NULL, and subscription or billing activity for the same accounts. If those accounts are still transacting, the users did not leave.
  5. Publish an ex-iOS total with an explicit annotated break rather than a blended total. A blended number during a known ingestion gap is wrong in a direction you can already name, and republishing it daily spreads the artefact into every downstream report.

Follow-up

  • Suppose the events do eventually backfill. What is your policy for restating the published weekly numbers, and who needs to be told?
  • What monitor would have caught this before a human noticed the weekly metric, and what would it alert on?
  • If is_core_action is maintained in the tracking plan, what governance would stop a change to that list from silently moving a north-star metric?

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.

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.

Discuss a time when you had to convince stakeholders of your model's value.

Medium · behavioural and stakeholder questions

Approach

  1. State the situation in two sentences and spend the rest on your reasoning.
  2. Quantify the outcome, including what you would not claim credit for.
  3. Pick a story where you drove the decision, not one where you observed it.

Follow-up

  • How did you know the outcome was caused by your change?
  • What would you do differently if you ran that project again?

Describe a challenging project you worked on and how you overcame obstacles.

Medium · behavioural and stakeholder questions

Approach

  1. State the situation in two sentences and spend the rest on your reasoning.
  2. Close with what you would do differently, concretely.
  3. Pick a story where you drove the decision, not one where you observed it.

Follow-up

  • What did you decide not to do, and why?
  • What would you do differently if you ran that project again?

Walk through an analysis you got wrong and what changed

Easy · postmortem · data quality · self-assessment

Describe an analysis of yours that turned out to be wrong after somebody had already acted on it. You have four minutes. The account must name the defect mechanically, the join, the filter, the window or the identity key, rather than describing it as a communication problem. It must also say who did what because of the wrong number, how the error surfaced, how long it stood, and what control you put in place so that class of error cannot reach a decision again. Do not pick an error nobody acted on.

Approach

  1. Recognise what is being probed: whether you can be specific about your own failure without minimising it or performing contrition. The discriminator is whether the defect has a mechanism the listener could reproduce in their own warehouse.
  2. Choose the case by blast radius rather than by comfort. An error nobody acted on tests nothing, and picking one signals that you are managing the interview instead of answering it.
  3. Structure the account in six beats: the number, the decision it drove, the defect, the detection, the correction, the control. Keep the defect to one reproducible sentence, for example an inner join to fct_subscription_period that dropped accounts with no subscription row and so computed retention over payers only.
  4. State the direction of the bias, not only its existence. A filter or join that removes rows usually moves a metric predictably, and knowing which way shows you diagnosed the mechanism rather than patched the symptom.
  5. Be exact about detection and elapsed time. 'A colleague noticed' and 'the row-count assertion failed before publication' are different answers about the same organisation, and the second one is the one your control is supposed to produce next time.
  6. End on the control, its cost, whether it has fired since, and one thing it does not cover.

Follow-up

  • What did the control cost, and has it fired since? If it never has, how do you know it works?
  • How long did the wrong number stand before anyone questioned it, and what does that say about the review path it went through?
  • What is the equivalent mistake you are most likely to make in this role, given the tables you would be working in?