The role of a Data Scientist at Navan is pivotal in harnessing the power of data to drive strategic decision-making and enhance user experiences across various products. As a Data Scientist, you will work on complex datasets to uncover actionable insights, optimize processes, and influence product development. This role is essential not only for maintaining the competitive edge of Navan's offerings but also for ensuring that data-driven decisions align with the needs of users and the business.
In your capacity as a Data Scientist, you will engage with diverse teams, including product management, engineering, and operations, to tackle real-world challenges. You'll be involved in projects that range from developing predictive models to conducting exploratory data analysis that informs product features and enhancements. This role promises to be both challenging and rewarding, allowing you to contribute directly to the strategic objectives of Navan while working in a dynamic and innovative environment.
Initial Screening Interview
reportedMost candidates lose this call inside the first two minutes, during the walkthrough of their own background. The account runs chronologically, sits at the level of tools and titles, and never arrives at a decision anyone could have disagreed with. Anchor on a problem instead of a timeline: what the team could not answer, what you did about it, what happened next. Ninety seconds is enough, and stopping on time leaves room for the half of the call that belongs to you. What you ask about how work gets prioritised signals your level more reliably than the walkthrough does.
What to demonstrate
- Whether your background summary has a shape (problem, decision, consequence) or is a chronological list of tools and employers
- Whether you can account for gaps, short stints and the reason you are looking, unprompted and without hedging
- The substance of the questions you ask back, which an experienced screener reads as a level signal
How to prepare
- Time your opening walkthrough against a clock. If it runs past two minutes, compress the earliest role into a single clause and spend the recovered time on the most recent one
- Write one honest sentence for every gap or short stint visible on your resume and offer it before being asked about it
- Prepare questions about how work arrives and gets prioritised: who writes the request, how often priorities change, and what happens to an analysis after it is delivered
Case Study Presentation
reportedThis round runs as a working session, so part of what it decides is whether you are useful to think with. The interviewer will interrupt: a hint that the data you assumed does not exist, a challenge to your metric, a nudge toward a branch you skipped. Treating those as interference is the common failure. Reason out loud while your thinking is still provisional so there is something to react to, and when a redirect arrives, take it instead of defending the path you had already started down.
What to demonstrate
- Whether your reasoning is audible while it is still unsettled, or only after you have privately decided
- What you do with a hint: absorb it and adjust, or argue for the original route
- Whether your clarifying questions have answers that would change your approach, as opposed to filling silence
- Whether you can be wrong about something in the middle of the case and keep moving without restarting
How to prepare
- Run practice cases with a partner instructed to interrupt twice: once to remove a data source you assumed existed, once to reject the metric you chose. Practise absorbing both without going back to the start.
- Before each practice case, write down the clarifying questions you plan to ask, then check afterwards whether any answer actually changed what you did. Drop the ones that did not.
- Explain an analysis you already know well to someone outside the field and have them stop you at every point where the reasoning jumped a step.
Technical Assessments
reportedThis 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
Discussions with Team Leaders
reportedBecause 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.
PracHub editorial advice for the preparation topics above.
Reading cancellation, completion or repeat rates on cohorts that have not matured
A cohort of bookings made last week for stays six months out cannot have cancelled at the check-in gate yet, so its cancellation rate is mechanically near zero and its completion rate mechanically near zero as well, in opposite directions. Comparing that cohort with a mature one is not a noisy comparison, it is a guaranteed wrong one, and the bias always makes the recent period look different in a way that invites a false story about a recent change. Because lead time is heavily right-skewed, the mean lead time is a bad maturity threshold; use the cohort's 95th percentile, or report a hazard at a fixed age (cancelled within k days of booking) with k capped at the youngest cohort's elapsed age. The same applies to repeat rate, where the honest answer is often that the cohort in question is not readable for another nine months.
Reporting on the booking date when the question is about the stay date, or the reverse
The same booking contributes to demand in one period and to revenue, occupancy and supplier payout in another, so almost every headline number has two defensible values that can differ by tens of percent. A promotion that moves bookings this week for stays in March produces a revenue 'drop' on the stay axis and a spike on the booking axis, and both are real. Cancellations make it worse, because a cancellation dated today removes revenue from a stay date months out and will silently restate a period that was already reported closed. The only defence is to name the date axis in the title of every chart and every metric definition, and to keep a pace view (bookings-on-hand for a future stay date, by days out) as a separate artefact rather than trying to serve both from one table.
Reaching for a model before the target metric exists
Before naming an algorithm, write down the label, the prediction time, and the action that changes when the score crosses a threshold. If you cannot say what decision the output drives, any modelling choice is guesswork dressed up as method.
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.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
What metrics would you use to evaluate a model's performance?
What metrics would you use to evaluate a model's performance?
Approach
- Set a baseline first, so any model has something honest to beat.
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
Follow-up
- What would you monitor after launch to know the model is still valid?
- Where could label leakage enter this setup?
Implement occupancy, ADR and revenue per sellable night
Two DataFrames: nights (booking_id, stay_date, supply_unit_id, night_status in booked/cancelled/no_show/stayed, unit_revenue_usd, taxes_and_fees_usd) and snap (supply_unit_id, stay_date, snapshot_date, units_available, units_sold_to_date, units_blocked). Implement, per stay_date: occupancy, average daily rate and net revenue per sellable night. Sellable nights are units_sold_to_date + units_available taken from the latest snapshot_date on or before that stay_date, per unit, excluding units_blocked. ADR excludes taxes. Return one frame indexed by stay_date and assert revenue-per-sellable-night equals ADR times occupancy.
Approach
- State the denominator convention out loud before coding: sellable nights exclude units_blocked, physical capacity includes them, and the two diverge sharply for individually-managed supply. Put the chosen convention in a column name or a returned attribute so a reader cannot mistake which one they are looking at.
- Do the as-of pick per (supply_unit_id, stay_date), not globally: filter snap to snapshot_date <= stay_date, sort by snapshot_date, then groupby(['supply_unit_id','stay_date']).tail(1). Taking the single latest snapshot_date across the whole table silently uses one date's view for every stay date and quietly changes the metric.
- Take the numerator only from
nightswith night_status == 'stayed'. units_sold_to_date at the final snapshot exceeds the stayed count by whatever cancels or no-shows afterwards, so reading the numerator off the snapshot overstates occupancy by exactly the late-cancellation rate. - Aggregate as a ratio of sums: sum the numerator and the denominator to stay_date grain and divide once. Averaging per-property occupancies or per-property ADRs is a mean of ratios and breaks the identity, weighting a four-unit property the same as a four-hundred-unit one.
- Assert the identity with np.isclose on relative tolerance: revenue/sellable equals (revenue/stayed) times (stayed/sellable) is exact arithmetic when all three are computed over the same unit-date set, so a failure means the sets differ, usually a unit present in
nightsbut missing from the snapshot.
Worked solution 30 min
- Filter snap to snapshot_date <= stay_date, sort by ['supply_unit_id','stay_date','snapshot_date'], take .groupby(['supply_unit_id','stay_date']).tail(1) as the as-of row.
- Compute sellable = units_sold_to_date + units_available on those rows, and sum to stay_date grain; keep the per-unit frame around for the coverage check.
- Filter nights to night_status == 'stayed'; sum unit_revenue_usd (taxes excluded) and count rows, both to stay_date grain.
- Left join on stay_date, then divide: occupancy = stayed / sellable, adr = revenue / stayed, revpan = revenue / sellable.
- Assert np.isclose(revpan, adr * occupancy, rtol=1e-9) and report any stay_date where the unit sets differ between the two sources.
Follow-up
- Occupancy comes out above 1.0 on three stay dates. Give the two most likely causes and how you would tell them apart.
- Rewrite the denominator on the physical-capacity convention. Which direction does occupancy move, and for which supplier type does the gap get large?
- Now split by property_class. Why can every class's occupancy rise while the blended figure falls?
Write invariant checks for a rate availability snapshot
The DataFrame snap holds one row per supply_unit_id per forward stay_date per snapshot_date, with units_available, units_sold_to_date, units_blocked, listed_price_usd (nullable), is_closed_to_arrival, min_length_of_stay and lead_time_days. Write check(snap) returning a tidy failure frame with columns check_name, supply_unit_id, stay_date, snapshot_date, detail, plus a per-check summary count. Cover at least: primary-key uniqueness, lead_time_days equal to (stay_date - snapshot_date) in days, listed_price_usd null exactly when units_available is 0, and non-negative counts. It must return the right empty frame on empty input.
Approach
- Write each check as a boolean mask over the whole frame, not a row-wise function, and append a small frame carrying check_name plus the three key columns and a
detailstring built from the offending values. Concatenate at the end with a typed empty frame in the list so an all-clean or empty input still returns the declared columns and dtypes. Declare the check names once as a module-level tuple, CHECK_NAMES, and drive both the run loop and the summary off that tuple rather than off whatever happened to fail. - Test nullity with .isna(); listed_price_usd is a float column so a NULL is NaN, and NaN == NaN is False, which means any
== Noneor== np.nancomparison returns an all-False mask and the check passes vacuously on every row. - Check the price rule in both directions: a non-null price where units_available is 0 means someone imputed the last known price onto a sold-out unit-date, which is the single most damaging corruption here because it turns censored observations into apparently-observed ones for any elasticity work.
- Separate hard invariants from business expectations and label them with a severity column. Uniqueness of (supply_unit_id, stay_date, snapshot_date), the lead-time identity and non-negativity are invariants. Monotonicity of units_sold_to_date across snapshot_date is not: cancellations legitimately reduce cumulative pickup, so it belongs at warn severity with a threshold on the size of the drop.
- Build the summary by grouping the failure frame on check_name and then reindexing against CHECK_NAMES with fill_value=0. A bare groupby emits no row for a check that found nothing, so a clean input returns a summary listing only the broken checks and an empty input returns no summary at all — which on a dashboard is indistinguishable from the suite never having run, the one state a summary exists to rule out. Return counts per stay_date alongside it so a caller can see whether failures are uniform or concentrated on a single partition, which is what distinguishes a code bug from one bad ingest day.
Follow-up
- Which of your checks would you make a hard pipeline failure and which a warning, and what is the cost of getting that wrong in each direction?
- units_sold_to_date drops by 4 between two consecutive snapshots for one unit-date. Give two innocent explanations and one that should page someone.
- How would you run these on a table too large to hold in memory, keeping the same failure frame?
Can you demonstrate how to visualize data using a Python library?
Can you demonstrate how to visualize data using a Python library?
Approach
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- Say which table is the grain you start from, and join outward from it.
- State the window function and its partition and ordering out loud before writing it.
Follow-up
- What breaks if events arrive late or out of order?
- How would you verify this result without re-running the same query?
Write a SQL query to find the top 10 products by sales volume.
Write a SQL query to find the top 10 products by sales volume.
Approach
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- State the window function and its partition and ordering out loud before writing it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
Follow-up
- How does the query change if the join becomes one-to-many?
- How would you verify this result without re-running the same query?
Zero-result search rate by market and lead-time bucket
fct_search has one row per submitted search: search_id, searched_at_utc, destination_market_id, lead_time_days, length_of_stay_nights, results_returned_count and is_bot_flagged. Write one query returning, per destination_market_id, per lead-time bucket (0, 1-7, 8-30, 31-90, 91+ days) and per ISO week of searched_at_utc, the count of searches that returned nothing, the count of non-bot searches, and the zero-result rate. Exclude is_bot_flagged rows from both numerator and denominator. The weekly figure must be re-summed from the underlying counts rather than averaged from daily rates.
Approach
- Apply the is_bot_flagged filter once in a base CTE so numerator and denominator are drawn from the same set; a filter applied only to the denominator can push the rate above 1 on a bot-heavy day.
- Bucket the stored lead_time_days column with a CASE expression rather than recomputing check_in_date minus the search date; the stored value is frozen and survives date amendments, so it matches the rest of the metric tree.
- Aggregate with COUNT() FILTER (WHERE results_returned_count = 0) alongside COUNT(), which produces numerator and denominator in one pass and guarantees they share a group.
- Group by market, bucket and DATE_TRUNC('week', searched_at_utc), then compute the rate as the ratio of the two summed counts at the week grain.
- Return both raw counts next to the rate so a consumer can re-aggregate across markets, across buckets, or to a multi-week period, without returning to the source table. Note the limit of that promise: week buckets are not nested inside calendar months, so a monthly figure is not reachable from this output.
Worked solution 20 min
- Count raw rows and bot-flagged rows over the window first, so you know how much the bot filter removes before you trust any denominator.
- Write the bucketing CASE and confirm every observed lead_time_days value lands in exactly one bucket, including zero and any negatives.
- Compute daily counts, eyeball one market for a single week, then wrap the result in the weekly aggregation.
- Compare the week's ratio-of-sums against the mean of the seven daily rates to see how far apart the two answers are on real data.
Follow-up
- Split the numerator into supply shortage versus restriction using fct_rate_availability_snapshot. How do you join it so you only see what the traveller could actually see?
- The rate jumped four points in one market last week. Which breakdown do you cut first, and what would make you believe it is a supply change rather than a demand mix change?
- Why is the UTC date of searched_at_utc the wrong day boundary for a market twelve hours ahead, and what would you group on instead?
You’re given a dataset with customer purchase history. How would you a…
You’re given a dataset with customer purchase history. How would you analyze it to improve retention rates?
Approach
- Fix the population and the time window before naming any metric.
- Decompose the metric into the rates that drive it, and say which one you would check first.
- 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?
- What would you do if the primary metric and the guardrail moved in opposite directions?
How do you prioritize tasks when working on multiple projects?
How do you prioritize tasks when working on multiple projects?
Approach
- State what result would change your recommendation, so the answer is falsifiable.
- Restate the decision this analysis has to support, and who acts on the answer.
- Fix the population and the time window before naming any metric.
Follow-up
- 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?
If you were tasked with predicting flight delays, what data would you …
If you were tasked with predicting flight delays, what data would you require and why?
Approach
- Fix the population and the time window before naming any metric.
- 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?
- Which segment would you cut first, and what would that rule out?
Describe how you would approach building a recommendation system for a…
Describe how you would approach building a recommendation system for a travel booking platform.
Approach
- Fix the population and the time window before naming any metric.
- Decompose the metric into the rates that drive it, and say which one you would check first.
- 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?
- What would you do if the primary metric and the guardrail moved in opposite directions?
Discuss your approach to A/B testing in a product feature rollout.
Discuss your approach to A/B testing in a product feature rollout.
Approach
- Decide the analysis before seeing data, including how long it runs and when you look.
- State the primary metric and the minimum effect worth shipping, then size the test.
- Name the guardrails that would stop a launch even on a positive primary result.
Follow-up
- What would you conclude if the result is positive but the test is underpowered?
- How would you handle interference between treated and control units?
Discuss a recent project where you applied statistical analysis.
Discuss a recent project where you applied statistical analysis.
Approach
- 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.
- Work from the decision backwards to the evidence you would need.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Choose a metric a cancellation-policy loosening cannot game
A team proposes converting a share of non_refundable inventory to refundable rate plans and expects more bookings. They want confirmed bookings per week as the success metric. Available: fct_booking (booked_at_utc, booking_status, rate_plan, lead_time_days, gross_booking_value, discount_amount_usd, platform_net_revenue_usd, refunded_amount_usd, cancellation_reason, servicing_contacts_count) and fct_stay_night (night_status, unit_revenue_usd, platform_net_revenue_usd). Say precisely how the proposed metric can be moved without one extra trip happening, propose a primary metric that cannot be moved that way, and name the guardrail that prices the change.
Approach
- State the gaming mechanism as a mechanism, not a risk: a refundable rate plan raises the count of booking_status = 'confirmed' rows on the day it ships and raises traveller-initiated cancellation months later, so the metric rises on the booking axis while completed stays are unchanged. The change buys optionality, not trips.
- Move the primary to the delivery grain: completed stay-nights from fct_stay_night with night_status = 'stayed', on the stay-date axis. A cancellation term cannot move it, because a cancelled night never reaches that state.
- Price the change with contribution margin per completed stay-night, since refundable inventory usually carries a higher headline rate but also refunds, chargebacks and servicing_contacts_count, and a rate_plan mix shift moves blended ADR through mix alone.
- Handle cohort maturity explicitly: a booking cohort cannot be read until its bookings have passed check-in, so pre-register a hazard at a fixed age - share cancelled within k days of booking, with k capped at the youngest cohort's elapsed age - as the interim read.
- Keep confirmed bookings as a published diagnostic next to rate_plan mix, so the mechanism stays legible to whoever reads the result, rather than deleting it and losing the story.
Worked solution 30 min
- Write the arithmetic of the gaming case: a 10 percent lift in confirmed bookings paired with the cancellation rate that refundable inventory carries, and show the completed-stay-night count that results.
- Define completed stay-nights per stay_date, stay axis, re-summed to week, and say why the booking axis cannot serve here.
- Define contribution margin per completed stay-night with its cost lines named: supplier payout, payment processing, refunds and chargebacks attributed back to those nights, and servicing cost allocated across the booking's nights.
- Choose k for the interim hazard from the youngest cohort's elapsed age and write the rule that k is fixed for every cohort in a comparison.
- Decompose ADR on stayed nights into within-rate_plan and mix components so that a mix-driven move is not read as a pricing effect.
Follow-up
- Completed stay-nights are flat and net revenue per sellable night is up. Would you ship it?
- How would you tell a genuine demand increase from travellers switching from non_refundable to refundable on trips they would have taken anyway?
- What would you need to see within four weeks to stop the rollout early?
Net revenue per sellable night fell six percent quarter over quarter
Net revenue per sellable night fell 6.1% quarter over quarter on the stay-date axis. Occupancy fell 4.6% and ADR fell 1.6%. Sellable nights rose 8%, and supply grew as planned. Using fct_stay_night, fct_rate_availability_snapshot and dim_supply_unit (property_class, listed_at_utc, listing_status, units_blocked), decompose the fall into rate and occupancy, then each of those into mix and within-segment, and determine how much is the mechanical effect of new supply entering the denominator before it sells. Deliverable: the decomposition with every term sized, and one recommendation.
Approach
- Verify the identity on your own row set before decomposing anything: revenue per sellable night equals ADR times occupancy exactly, because revenue/sellable = (revenue/stayed) times (stayed/sellable), and only when all three are computed over the same units and dates. Work in logs so the components add, and confirm that -1.6% and -4.6% reproduce -6.1%.
- Run shift-share on each component separately and on the same segmentation, market by property_class by lead-time bucket, using stayed nights as the weight base for ADR and sellable nights for occupancy. Each rate must be decomposed on the denominator it is actually built from, or the terms will not reconcile.
- Isolate the supply-cohort effect explicitly. Split units by listed_at_utc into those live in both quarters and those listed during the quarter, and recompute all three metrics on the stable cohort alone. New listings add sellable nights immediately and revenue only once they ramp, so the gap between the all-supply and stable-cohort figures is dilution, and dilution is not a performance problem.
- Check the denominator for the opposite artefact. A supplier blocking cheap dates raises this metric while shrinking supply, so confirm the sellable-night convention did not change between quarters, and report sellable nights as a level rather than only as a denominator.
- Assemble one table with within-segment rate, mix rate, within-segment occupancy, mix occupancy, new-supply dilution and residual, and either make the residual small enough to ignore or explain it.
- Recommend only after the table exists. If the fall is dilution plus mix, cutting price attacks the one term that was already healthy and makes the next quarter worse.
Follow-up
- New supply accounts for 70% of the fall. At what point does that stop being dilution and start being a ramp problem you should act on?
- How would you report this metric so that next quarter's supply growth does not make the number look good for the wrong reason?
- Which of these terms could a supplier-facing team actually move, and over what horizon?
For a candidate whose interviews will centre on A/B testing, metric movement and causal claims. Design comes before arithmetic, arithmetic before analysis, and the week ends by rehearsing the readout rather than the derivation.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Design one test end to end on paper
- Take a single feature change and write the full design: randomization unit, the exact point of exposure, the primary metric with its grain, guardrails, allocation, planned duration, and the decision rule committed before any data exists.
- Write why the randomization unit must sit at or above the level where treatment can spill over, and give one case where user-level randomization is still contaminated (shared accounts or devices, or two participants in the same marketplace).
- State in advance what you will do if the primary metric is flat while a secondary metric is significant.
Deliverable: A one-page test design with a decision rule written before launch.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Power arithmetic until it is automatic
- Compute required sample size per arm for a binary metric with the normal approximation, n is approximately 2 times (z for alpha/2 plus z for power) squared times p(1 minus p) divided by delta squared, for baselines of 2, 10 and 40 percent at a 5 percent relative lift, and note that for a fixed relative lift the requirement falls as the baseline rises because delta grows proportionally with p.
- Redo the calculation for a continuous metric using variance in place of p(1 minus p), and show why a heavy-tailed quantity such as revenue per user needs either far more traffic or a capped version with a stated cap.
- Convert one of the results into weeks given a weekly eligible traffic figure, then list the two honest ways to shorten it (accept a larger detectable effect, or reduce variance) and write why quietly lowering the power target is a decision to miss more real wins, not a speedup.
Deliverable: A small script or sheet that maps baseline, minimum detectable effect, alpha and power to sample size and weeks, cross-checked against a published calculator.
Practice prompt ↗Practice prompt ↗Practice prompt ↗03Variance and the unit-of-analysis problem
- Take a ratio metric whose denominator is not the randomization unit (clicks per session, randomized by user) and compute the standard error twice, once naively at session level and once by the delta method or a user-level bootstrap, then record how much the naive version understates it.
- Implement CUPED on simulated data: choose a pre-period covariate X measured before assignment, estimate theta as Cov(Y, X) divided by Var(X), and analyse Y minus theta times (X minus its mean) in place of Y. Confirm the variance of the adjusted outcome equals the raw variance multiplied by one minus the squared correlation between Y and X, so a correlation of 0.45 removes about 20 percent of the variance and not 80.
- Now run that simulation a few hundred times and confirm the adjusted effect estimate is unbiased for the same effect rather than numerically identical to the raw one. Within any single run the two differ, sometimes by a large fraction of the true effect, because the two arms' pre-period covariate means never coincide exactly in a finite sample; they agree in expectation, which is the property that matters and the one to state out loud.
Deliverable: A notebook showing the adjusted estimator with a measurably smaller variance than the raw one, plus a repeated-simulation table showing the two estimators agreeing on average while differing run by run.
Practice prompt ↗Practice prompt ↗Practice prompt ↗04Validity threats you can actually test for
- Run a sample ratio mismatch check as a chi-square goodness-of-fit test against the intended allocation, and write the three causes you would chase first (assignment logged before exposure, an arm-specific redirect or load failure, bot filtering applied asymmetrically).
- Simulate peeking: generate A/A data, test daily at alpha 0.05 across 14 looks, record the inflated false positive rate, then apply an alpha-spending boundary or commit to a fixed horizon and confirm the rate returns to nominal.
- Write how you would separate a novelty effect from a durable lift using the treatment effect plotted against days since first exposure, and what shape would change your recommendation.
Deliverable: One table showing the peeking false positive rate before and after correction, plus a written SRM triage list.
Practice prompt ↗Practice prompt ↗Worked solution ↗05When randomization is not available
- Write the identifying assumption for difference-in-differences (parallel trends in the absence of treatment), then plot pre-period trends for two candidate control groups and justify rejecting one of them.
- Design a switchback test for a change where user-level randomization would leak across participants, choosing a time-block length against the carryover you expect and saying how you would detect carryover in the data.
- List what an interrupted time series or a synthetic control buys you and the one thing neither can rule out: an unobserved shock that coincides with the launch.
Deliverable: A one-page memo recommending a single quasi-experimental design and naming its weakest assumption explicitly.
Practice prompt ↗Practice prompt ↗06The readout query
- Write the assignment-to-exposure join that returns exactly one row per unit per experiment, and handle units appearing in both arms by excluding and counting them rather than silently keeping one.
- Compute the per-arm metric, its variance and the relative lift with a confidence interval in SQL, then reproduce the identical numbers in a notebook as a cross-check.
- Add a segment breakdown and write the sentence that keeps it from being p-hacking: segments declared in advance, everything else reported as exploratory and corrected for multiplicity.
Deliverable: A single query that outputs the full readout table, matched to a notebook recomputation.
Practice prompt ↗Practice prompt ↗07Present it to someone who will not read the appendix
- Give a 10-minute readout of a real or simulated experiment in the order decision, number, uncertainty, caveat.
- Have your listener ask "can we ship it" in the case where the primary is flat and a guardrail moved, and answer with a recommendation rather than a request for more data.
- Rewrite your opening line so the recommendation lands before any methodology.
Deliverable: A one-page readout whose first line is the recommendation.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Half of this section is about translation. Be ready to describe how you explained a result to someone who did not want the method, only the implication, and what you did when the simplified version started being repeated in a way that overstated it. Correcting your own simplification is a strong beat.
How do you handle missing data in a dataset?
How do you handle missing data in a dataset?
Approach
- Name the disagreement or constraint, and how you resolved it with evidence.
- State the situation in two sentences and spend the rest on your reasoning.
- Pick a story where you drove the decision, not one where you observed it.
Follow-up
- What would you do differently if you ran that project again?
- How did you know the outcome was caused by your change?
Give an executive one number and its honest interval
A director must commit contact-centre staffing for a peak stay-week 60 days out. Your pickup forecast from fct_rate_availability_snapshot gives 42,000 stayed nights for that week, with an 80% interval of 36,500 to 47,000. Back-testing shows the interval only narrows materially inside 30 days out. The director has said twice that they want one number and do not want to hear about confidence intervals. You have a five-minute slot and one slide. Prepare what goes on it and what you say.
Approach
- Work out the decision before the number: staffing is asymmetric, because under-staffing a peak week costs servicing failures and cancellations while over-staffing costs idle hours. Find out which side is more expensive, because the whole answer is which end of the interval to plan against.
- Convert the interval into two staffing levels rather than two stay-night counts. An executive cannot act on 36,500 to 47,000; they can act on 'staff for 44,000 now, with a named trigger to add or release capacity'.
- Give the one number they asked for, and attach the trigger to it rather than a caveat: plan at the level implied by the more expensive error, then re-read pickup at 30 days out, which back-testing says is where the interval actually moves.
- Say what the uncertainty is made of in one line each, using the domain's own vocabulary: pickup still to come, lead-time mix for that market, and whether the week straddles a moving holiday that shifts against last year.
- Close with the decision the interval does not affect, so the director knows the width is not an excuse: if every point in the interval implies the same staffing tier, say so and stop talking about the interval.
Follow-up
- The week lands 6,000 nights below your point forecast. How do you handle the next forecast conversation with this director?
- They ask you to just give them the midpoint and skip the trigger. What do you do?
- How would you decide whether an 80% interval is the right one to show rather than a 50% or a 95%?
State your own impact when the evidence is confounded
You built the pickup-based stay-week forecast that replaced a trend model, and it was adopted across markets last quarter. Forecast error on stay-week stayed nights improved 9% over the quarter. In the same quarter two markets were added to the portfolio, the seasonality baseline was re-fitted by another team, and one large market's moving holiday realigned against the prior year. You are writing the impact section of your own review. Write the claim you would actually make, the evidence behind it, and what you explicitly do not claim.
Approach
- Name the counterfactual before the number: 9% against what the old model would have produced on the same weeks, not against last quarter's realised error, since the portfolio and the calendar both changed underneath.
- Build the honest comparison by back-testing the old model on the current quarter's stay weeks and scoring both models on the same weeks, same markets, same horizon. This removes the two added markets and the re-fitted baseline from the comparison entirely, because both models see the same inputs.
- Handle the moving holiday by excluding or separately reporting the affected stay weeks, since a realignment changes the difficulty of the forecast rather than the quality of either model, and it would otherwise sit inside your credit.
- Split the claim into what the method did and what you did. Adoption across markets involved other people; the defensible personal claim is the method and the migration you drove, with the organisational result reported alongside and attributed plainly.
- Write the non-claim explicitly and early. Stating that you cannot attribute the portfolio-level improvement to the model alone is what makes the part you do claim credible, and it pre-empts the reviewer finding the confound themselves.
Follow-up
- The head-to-head back-test shows only a 3% improvement. What do you write?
- How would you have instrumented the rollout so this was measurable without a back-test?
- A peer's review claims the same 9%. How do you handle that?
- 01
How do you handle missing data in a dataset?
- 02
A director must commit contact-centre staffing for a peak stay-week 60 days out. Your pickup forecast from fct_rate_availability_snapshot gives 42,000 stayed nights for that week, with an 80% interval of 36,500 to 47,000. Back-testing shows the interval only narrows materially inside 30 days out. The director has said twice that they want one number and do not want to hear about confidence intervals. You have a five-minute slot and one slide. Prepare what goes on it and what you say.
- 03
You built the pickup-based stay-week forecast that replaced a trend model, and it was adopted across markets last quarter. Forecast error on stay-week stayed nights improved 9% over the quarter. In the same quarter two markets were added to the portfolio, the seasonality baseline was re-fitted by another team, and one large market's moving holiday realigned against the prior year. You are writing the impact section of your own review. Write the claim you would actually make, the evidence behind it, and what you explicitly do not claim.
Is this an official Navan interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Navan. Rounds and questions reflect what candidates have reported, not a process Navan has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗What is the typical interview difficulty for this position?
The interview process is generally considered average in difficulty, but candidates should be prepared for rigorous technical assessments and case studies.
PracHub interview research ↗How can I differentiate myself as a candidate?
Successful candidates often demonstrate a deep understanding of data science concepts, showcase relevant project experience, and communicate effectively with both technical and non-technical audiences.
PracHub interview research ↗What is the typical timeline from application to offer?
Candidates can expect the process to take several weeks, usually around three to eight weeks, depending on scheduling and team availability.
PracHub interview research ↗What is the company culture like at Navan?
Navan fosters a collaborative and data-driven culture, emphasizing efficiency and innovation while valuing diverse perspectives and teamwork.
PracHub interview research ↗Sources & methodology 3 sources ↗
No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
PracHub page · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
PracHub page · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
PracHub page · Accessed 2026-09-22