The 60-second brief
At Wayfair, data is not just an asset—it is the engine that powers every aspect of the e-commerce experience. As a Data Scientist, you will operate at the intersection of technology, machine learning, and business strategy. Your work will directly impact millions of active customers and influence how billions of dollars in inventory move across a global supply chain. You will be responsible for translating complex, high-dimensional data into actionable algorithms that drive real-time decision-making.
Wayfair candidates report 4 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
What a Data Scientist does at Wayfair
The scope of a Data Scientist at Wayfair is incredibly diverse, spanning several specialized domains. You might find yourself optimizing dynamic pricing engines, developing advanced recommendation systems to personalize the customer storefront, building predictive models for logistics and supply chain routing, or designing sophisticated bidding algorithms for marketing channels. Because Wayfair operates at an immense scale, the models you build must be robust, scalable, and highly performant.
What makes this role uniquely challenging and rewarding is the direct line of sight between your models and business outcomes. You will not build models in a vacuum. Instead, you will work closely with product managers, engineers, and business leaders to deploy your solutions, measure their impact through rigorous experimentation, and iterate rapidly. Success in this role requires not only deep technical expertise but also strong business acumen and the ability to navigate ambiguity.
The Wayfair interview process
Wayfair candidates report 4 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
Online Assessment
A handful of shapes account for most of what gets asked in this format: a ranking or deduplication inside groups, a running or rolling total, a period-over-period comparison, and a cohort tracked forward over time. Recognising the shape quickly is most of the speed here; deriving it from scratch while a clock runs is where the time goes. Know that a window function keeps every row while a GROUP BY collapses them, and know which one the question needs. If the exercise is in Python instead of SQL, the same shapes arrive as groupby with transform, shift and merge, and the same grain mistakes are available.
What it evaluates
- Whether you reach the right construct without a detour, such as ROW_NUMBER over a partition to deduplicate instead of a self-join against a MAX subquery
- Whether you know what your window frame actually is, since adding ORDER BY inside OVER changes the default frame and silently changes a running total
- Whether the thing runs. A near-miss that throws an error scores below a plainer query that returns the right rows.
How to prepare
- Write each of the four shapes once from memory against a small schema and keep the working version somewhere you will reread it: dedupe with ROW_NUMBER, a running total, a month-over-month change with LAG, and a retention table
- Compute one running total twice on data with tied timestamps, once on the default frame and once with ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and look at where the two disagree
- If Python is on the table, rebuild the dedupe and the running total with groupby and cumsum, then assert the two implementations return identical rows
Recruiter Screen
Most 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 it evaluates
- 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
Technical Interviews
Much of what gets scored here happens out loud while you type. Nobody can see your reasoning inside a half-written query, so five silent minutes read as being stuck even when they are not. State the plan in plain language first: which tables, what grain you are aggregating to, and the one filter that defines the population. Then write it. The narration doubles as insurance, because a wrong plan gets caught early and cheaply while a wrong query gets caught at the end with no time left to redo it. A timed statistics section, where one exists, is a separate test with its own clock.
What it evaluates
- Whether the query you write matches the plan you just described
- What you do with a hint, meaning whether the correction gets absorbed or the first approach gets defended
- Whether you can debug your own wrong output by reading the result set and naming which part of the query produced the anomaly
How to prepare
- Solve three problems while screen-sharing into a recording, then watch it back and mark every stretch longer than thirty seconds where you said nothing
- Practise compressing the plan into one sentence before typing, then check afterwards whether the finished query actually matched it
- Time yourself on statistics questions that carry a business reading, such as what a confidence interval does and does not claim, rather than re-reading notes without a clock
Final Round
A day of back-to-back interviews samples your floor, not your ceiling. Four hours in, the habits that carry a good answer are the first to go: restating the question before solving it, asking what the data would have to look like, checking a number before quoting it. What the day decides is whether the tired version of you is still someone to leave alone with an ambiguous problem. The round that sinks a candidate is usually not the hardest one. It is the one immediately after the round that went badly.
What it evaluates
- Whether the late rounds get the same clarifying questions as the first one, or whether you start answering immediately to save effort
- Whether a weak answer stays in the room it happened in, instead of following you into the next conversation as apology or distraction
- Whether the quality of your questions holds up, since fatigue removes curiosity about the problem before it removes knowledge of the method
How to prepare
- Rehearse the length, not just the content: book four mock interviews of different types in one afternoon with short gaps, because the one you need to observe is the fourth
- Put the two or three questions you ask at the start of any problem on a card in front of you, so that under fatigue it is a habit you run rather than a decision you make
- Decide in advance what the gap between rooms is for: water, one line of notes on anything you promised to follow up, and an explicit close on the round that just ended so it does not travel
- Prepare a different closing question for each interviewer, so the end of a long day does not produce the same one four times
Questions Wayfair candidates report
These are the prompts PracHub has collected for this role and company. They are a record of what candidates describe being asked, so treat them as the shape of the conversation rather than a script Wayfair works from.
Product sense and metrics
Every question in this group starts from the same move: name the outcome the product is supposed to produce, then name the number that would show it happening. Work forward from the mechanism, not backward from a metric you already like. Ask what behaviour changes, for whom, and how soon, and only then pick the measure that sits closest to that behaviour without being trivially satisfied by it. What usually separates answers is the counterfactual. A candidate who says what result would make them call the change a failure has defined success; one who only describes what going well looks like has not.
- How do you prioritize your work when you are flooded with requests from multiple product and business teams?
SQL and data manipulation
These questions are rarely hard to solve and easy to get subtly wrong in the minutes available, so how you spend the clock is part of the answer. Write the filter and the spine, run it, look at ten rows, then add one layer and run again. That costs seconds and catches the errors that otherwise arrive as a plausible number you cannot defend. Keep the last minute for checks that fit on one line: row count against distinct key count, funnel stages that should only shrink, and nulls where a left join found nothing. Say out loud what you checked.
- Write a SQL query to calculate the month-over-month retention rate of customers who made their first purchase in a specific category.
- How would you handle missing values and outliers in a highly skewed pricing dataset using Python?
- Write a query to find the top three highest-selling products in each sub-category for the past quarter, handling ties appropriately.
A/B testing and experimentation
The standard analysis assumes one unit's treatment cannot affect another unit's outcome. Say that assumption out loud, then ask where it breaks in the setting you were handed: shared supply, a shared budget, a ranking that reorders when other people click, any two-sided market where the arms compete for the same inventory. Interference does not merely add noise, it biases the estimate, and where the arms compete for scarce supply it usually flatters the treatment because the control group absorbs the cost. The answer that lands names the channel the spillover travels through, then changes the design rather than the test.
- We are considering a new promotional pricing strategy for outdoor furniture. How would you design an A/B test to measure its impact on net revenue and profit margin?
- If an A/B test shows a statistically significant increase in conversion rate but a decrease in average order value (AOV), how would you decide whether to roll out the feature?
Statistics and probability
Most of these questions end, explicitly or not, with a stakeholder who wants a decision and does not want a lecture, which makes precision of language the thing actually under test. A p-value is the probability of data at least this extreme if the null were true. It is not the probability that the null is true, and not the chance the result is a fluke. A 95% interval is a property of the procedure across repeated samples, not a 95% chance that this particular interval contains the parameter. Give the plain sentence that is still true, then the caveat that would change the decision.
- What are the pros and cons of using collaborative filtering versus content-based filtering for product recommendations on Wayfair's homepage?
Machine learning and modelling
Choose the evaluation metric from what is done with the score. If a fixed number of items go to human review each day, precision in that top slice is the metric and the score only has to order things correctly. If the score gets multiplied by a value to make an expected-loss decision, it has to be a calibrated probability, and area under the curve says nothing at all about that. Imbalance bites mainly here: resampling and class weights pull predicted probabilities away from the base rate, so anything that needed calibration needs recalibrating afterwards.
- How do you address class imbalance when training a binary classification model for fraud detection? Which evaluation metrics would you prioritize?
Behavioural and stakeholder questions
Some of these are less about conflict than about what you do with a vague request. Someone asks for a dashboard, or for a number by Thursday. Underneath it sits a decision somebody is about to make, and the first useful move is to find that decision and ask what they would do differently depending on the answer. Answers get noticeably stronger when you describe the scope you refused alongside the scope you took. Saying that you dropped two of five requested breakdowns because they could not be measured cleanly, and saying it before anyone asks, reads as judgement rather than as a shortfall.
- Describe a time when you had to explain a highly complex technical concept or model to a non-technical business stakeholder. How did you ensure they understood?
Practice exercises with worked solutions
The prompts above tell you what gets asked. These are PracHub exercises written to drill the same skills, with the reasoning spelled out so you can check your own answer instead of guessing whether it was good enough.
Daily visit-to-order conversion by device, excluding denied-consent sessions
From fct_session (session_id, started_at_utc, device_type, entry_channel, order_id, tracking_consent, is_bot_flagged), return visit-to-order conversion for the last 28 days split by device_type and entry_channel. A session converts when order_id IS NOT NULL. Exclude is_bot_flagged = TRUE, and exclude tracking_consent = 'denied' from both numerator and denominator, reporting the denied share of non-bot sessions as its own column. Then produce the weekly figure from the same base. Output: day or week, device_type, entry_channel, sessions, orders, conversion_rate, denied_share.
How a strong candidate works it
- Filter once in a base CTE (is_bot_flagged = FALSE, started_at_utc in the window) and carry tracking_consent through, so the numerator and denominator can never drift apart in two separate scans.
- Aggregate with conditional counts in a single pass: COUNT(*) FILTER (WHERE tracking_consent <> 'denied') as sessions, and the same filter plus order_id IS NOT NULL as orders.
- Divide at the end with a NULLIF on the denominator and a numeric cast, because integer division floors a 2 percent rate to 0.
- For the weekly number, group the same base on date_trunc('week', started_at_utc) and re-divide the summed counts; an average of seven daily rates weights a quiet Tuesday the same as a peak Saturday.
- Emit denied_share = denied sessions / all non-bot sessions beside the rate, so a consent-banner change that moves the denominator is visible rather than being read as a behaviour change.
Expected result (20 min): One row per (day, device_type, entry_channel) with sessions, orders, a conversion_rate between 0 and 1, and denied_share. The weekly rate equals SUM(orders)/SUM(sessions), and it exceeds the unweighted mean of the seven daily rates by exactly Cov(daily sessions, daily rate) / mean(daily sessions), the covariance taken over the seven days. So the two agree whenever the daily rates are flat, or whenever volume and rate are uncorrelated, however wide the traffic spread; they diverge only when volume and rate move together, which is the usual shape of a promotional weekend. Measure the gap on the actual week rather than asserting it is negligible or large.
Check yourself
- SUM(sessions) across all rows for a day equals the count of non-bot, non-denied sessions started that day.
- orders never exceeds sessions in any row.
- The difference between the two weekly figures matches Cov(sessions, rate) / mean(sessions) to rounding, which confirms the gap is the volume-rate relationship and not an aggregation bug.
- Replacing the seven daily rates with their mean (holding sessions fixed) collapses that difference to zero, which is the control that proves traffic dispersion alone does not create it.
- denied_share summed with the retained share equals 1 for every day.
Follow-ups
- Denied-consent sessions can still place orders. What does excluding them do when you reconcile session-attributed orders against total orders in fct_order_line, and how do you present that gap?
- Conversion rose on desktop and rose on mobile_web, but the blended rate fell. What happened, and what would you show to make it obvious?
- How would you handle a session that starts at 23:55 and places its order at 00:04 the next day?
Net revenue per order without fanning out return rows
You get two DataFrames. order_lines has order_line_id, order_id, customer_id, quantity, unit_paid_price_cents, line_status, delivered_at_utc. return_lines has return_line_id, order_line_id, quantity_returned, refund_amount_cents, initiated_at_utc. One order line can have several return rows. Produce one row per order_id with gross_cents over delivered lines only, refund_cents from returns initiated within 90 days of that line's delivery, net_cents, and units_kept. The output must have exactly one row per order_id, and gross_cents must equal a total you compute without ever touching return_lines.
How a strong candidate works it
- Filter order_lines to line_status == 'delivered' first, and compute gross_cents = quantity * unit_paid_price_cents per line. Keep that per-line frame as the control total before any merge.
- Aggregate return_lines to one row per order_line_id with groupby('order_line_id').agg(sum of quantity_returned, sum of refund_amount_cents, min of initiated_at_utc) so the right side of the join is unique on the join key.
- Because the 90-day window is per return row, not per order line, apply the window before aggregating: join initiated_at_utc against the parent line's delivered_at_utc, keep rows inside the window, then aggregate. Doing it after aggregation loses the individual initiation dates.
- Left merge the aggregated returns onto the delivered lines with validate='m:1' so pandas raises instead of silently duplicating, then fillna(0) on the refund and quantity columns.
- Group to order_id, sum gross_cents, refund_cents, and units_kept = quantity - quantity_returned, and assert the gross total equals the control total computed in step one.
Expected result (25 min): A DataFrame indexed by order_id with gross_cents, refund_cents, net_cents and units_kept, where gross_cents sums to the delivered-line total computed independently, and every order_line_id appears exactly once regardless of how many RMA rows it has.
Check yourself
- len(result) == order_lines.loc[delivered, 'order_id'].nunique()
- result['gross_cents'].sum() equals the control total computed before any join
- Setting validate='m:1' on the merge raises if the return aggregation was skipped
- net_cents <= gross_cents for every row, and units_kept is never negative
Follow-ups
- The order line was paid in a non-USD currency with fx_rate_to_usd on the line. Where does the conversion belong, and what breaks if you convert after aggregating to order grain?
- Refunds arrive weeks after the order. Which date do you attribute refund_cents to when you report a monthly net revenue series, and why does the answer change how long you must hold the report back?
- How would the query change if a partial return could be refunded in two instalments under the same rma_id?
A ranking test that starves its own control arm
A ranking change promotes high-margin SKUs that have low days_of_cover in fct_inventory_snapshot. In a 50/50 visitor-level test, treatment converts 6 percent better. Inventory is pooled across arms: available_to_promise_units is shared at the node, so demand created by treatment raises minutes_unavailable and units_cancelled_oos for control visitors too. Explain why the 6 percent is biased and in which direction, name the evidence in fct_inventory_snapshot and fct_order_line that would confirm it, and design a version of the test whose estimate is not contaminated. State the analysis unit and what it costs.
How a strong candidate works it
- Name the SUTVA violation precisely: a control visitor's outcome depends on treatment assignment of other visitors through the shared inventory pool, so the estimate is not the effect of the ranking change but the effect of the change plus the damage it does to the comparison group.
- Fix the sign. Treatment depletes stock of the SKUs it promotes, control then sees those SKUs unavailable and converts worse than it would under full control, so the measured contrast overstates the true effect. A rollout to 100 percent removes the starved comparison and the lift shrinks.
- Gather the evidence rather than asserting it: join fct_inventory_snapshot on the promoted SKU set and compare minutes_unavailable and units_cancelled_oos against the pre-period, and check whether control-arm conversion fell relative to its own pre-period rather than only against treatment. Check whether the lift concentrates in SKUs with low days_of_cover.
- Redesign. The cheapest option restricts the promoted set to SKUs with days_of_cover above a threshold, which removes the interference but also removes the case the change was built for. Cluster randomisation on fulfilment node or market works only where inventory pools are genuinely node-partitioned and orders are node-local, which the fct_order_line to fct_inventory_snapshot join on (node_id, sku_id, snapshot_date) lets you verify.
- Where the pool cannot be partitioned, use a switchback: apply one ranking to all traffic in randomised time blocks. Both arms then face the same inventory state within a block. Price it honestly: the analysis unit becomes the block, not the session, and the sample size collapses to the number of blocks.
Expected result (40 min): The 6 percent is an upper bound: shared inventory means treatment degraded control. A 56-block switchback over 14 days removes the contamination but detects nothing smaller than about a 9 percent relative change, so the measurable effect must be large or the design must instead partition inventory by node.
Check yourself
- Control-arm conversion compared with its own pre-period should be flat if there is no interference and down if there is; this test does not require the treatment arm at all.
- In a valid switchback, the pre-period block-level metric should show no difference between the block sets that will later be assigned to each arm.
- The between-block coefficient of variation used for power should be estimated from pre-period blocks of the same length, not assumed.
Follow-ups
- Inventory depletes from one block into the next. How long would you make a block, what burn-in would you discard, and what does carryover do to the estimate?
- If you cluster on fulfilment node, how would you check that orders are actually node-local before trusting the design?
Down nine percent against a week that is not comparable
The weekly business review shows merchandise revenue down 9% against the same calendar week last year, and the merchandising lead is proposing an unplanned markdown on the back of it. You have fct_order_line (placed_at_utc, placed_at_local, promotion_id, line_discount_cents, quantity, unit_paid_price_cents, currency_code, fx_rate_to_usd) and dim_customer (billing_country_code). Deliverable: state whether the published comparison is interpretable as it stands, produce the comparison you would defend instead, and quantify how much of the 9% survives it.
How a strong candidate works it
- Establish the calendar the business actually plans on. Retail planning runs on a 4-5-4 fiscal calendar, so map both weeks to fiscal week numbers, and check whether a 53-week fiscal year sits between them, which shifts every subsequent week by one against the Gregorian date.
- Align the promotional calendar, not just the dates. Pull promotion_id activity and weekly promotional depth (line_discount_cents over quantity * unit_list_price_cents) for both years and locate each event. Compare week-before-event, event week and week-after rather than date to date.
- Account for moving holidays per market using placed_at_local and billing_country_code, because an event that moves one week in one country and not another makes a blended comparison uninterpretable in both directions.
- When the weeks cannot be aligned one to one, widen to a window that fully contains the event in both years, typically three or four weeks, and compare the window totals in constant currency. State the window in the headline so nobody re-cuts it to a single week.
- Only on the aligned residual, decompose into traffic, conversion, units per order, price per unit and keep-rate, and say which of those, if any, justifies a markdown.
Follow-ups
- The fiscal calendar aligns the weeks but the event still straddles a boundary. What do you publish?
- How would you quantify pull-forward from last year's event so the week after it is not read as a collapse?
- The markdown is proposed anyway. What evidence would change your recommendation from no to yes?
Explain a forecast interval to an executive placing a buy
You forecast season demand for a style with a twelve-week lead time. The point forecast is 40,000 units and your eighty percent interval runs 26,000 to 61,000. The executive placing the purchase order asks for one number and says intervals are not actionable. Unsold units are marked down at end of season. A stockout loses the sale and censors the demand history you will forecast on next year. In four minutes, with no slides, give the executive a buy quantity and explain the uncertainty in terms they can act on.
How a strong candidate works it
- Name a quantity first, then explain it. Refusing to give a number reads as evasion, and the buy gets placed anyway without your input in it.
- Translate the interval into the decision. One unit too many costs the markdown loss; one unit too few costs the lost contribution plus the censoring it writes into next year's history. Those costs are not equal, so the right order quantity is not the median of the forecast.
- State the critical ratio rather than asserting a quantile: order the q-quantile of the demand distribution where q = Cu / (Cu + Co), Cu being contribution lost per unit short and Co being unit cost minus salvage recovery per unsold unit. This holds for a single ordering opportunity with no mid-season replenishment and a known salvage value.
- Express the remaining uncertainty as consequences rather than as a range: at your recommended quantity, the probability of selling out before end of season and the expected markdown units if demand lands near the top of the interval.
- Offer the lever that actually shrinks the interval: a smaller initial buy with an in-season reorder if any supplier lead time allows it, or a first-two-weeks sell-through read that updates the quantity before the second tranche.
- Agree what goes in writing: the number, the quantile it corresponds to, and the two per-unit costs it depends on, so the number survives being repeated without you.
Follow-ups
- What evidence would make you raise the number, and how quickly could you get it?
- Supply offers a second buy at week six with a shorter lead time but ten percent higher unit cost. How does that change your recommendation?
State the impact of your model without overclaiming
Writing your own review, you want to claim the reorder model you shipped in February. Since launch, demand-weighted in-stock rate on covered categories rose from ninety-one to ninety-five percent and net merchandise revenue on them is up eight percent year over year. In the same window a supplier consolidation shortened lead times, two categories were re-merchandised, and the fiscal calendar shifted the promotional week. Nobody will check your number. Write the impact claim you would actually put in the document, and explain what you did to earn the right to it.
How a strong candidate works it
- Decide what is attributable before deciding what is impressive. Three known changes move the same metrics in the same direction, so the year-over-year revenue figure is an upper bound rather than an estimate of your effect.
- Find the cleanest contrast still available after the fact: categories the model covers against comparable uncovered ones over the same weeks. That is a difference-in-differences read, its identifying assumption is parallel pre-trends, so show the pre-period rather than assert it.
- Claim the mechanism you can trace end to end. The model changed reorder points, reorder points changed minutes_unavailable, availability changed units sold. Each link is measurable, and a confounder has to break a specific one of them.
- Lead with the in-stock movement and put revenue second, because availability is closest to the thing you changed and hardest for the supplier consolidation to explain away.
- Write the confounders into the claim instead of omitting them. A claim that survives a reader naming the consolidation is worth more than a larger one you retract when they do.
- State the counterfactual you cannot rule out, and the design you would run next time to rule it out.
Follow-ups
- Your manager wants one number for the promotion packet. Which one, and what sentence goes with it?
- A peer claims the same revenue for the re-merchandising work. How do you resolve that without both of you shrinking your claims to nothing?
Where candidates lose points
Reading revenue or cohort value before the return window closes
Returns arrive days to weeks after delivery and vary enormously by category, so a two-week-old cohort reported on gross revenue is being compared with a mature cohort reported on something close to net. In apparel the gap between the two definitions is routinely twenty to forty percent of gross, more than the effect size of almost any experiment or campaign being evaluated. Attribute refunds back to the parent order's placed date rather than the refund date, hold the reporting lag at the 95th-percentile return-initiation lag for the category, and never let a fresh cohort's gross number sit in the same table as a mature cohort's net number.
Fitting demand models on sales when sales are censored by availability
Units sold equal the minimum of demand and what was sellable, so every day a SKU was out of stock contributes a zero that looks identical to genuine indifference. A model trained on that history forecasts the stockout, the buy shrinks, availability falls further, and the error compounds each cycle, which is why a declining SKU forecast should always be checked against minutes_unavailable before it is believed. The fixes are to restrict the fit to in-stock periods, to model availability explicitly as an exposure term, or to use a censored likelihood; all three require the availability history to be retained at a finer grain than a daily end-of-day snapshot, which is exactly what teams tend to discard.
Stopping an experiment the moment it crosses significance
Fix the sample size or duration before launch, or use a method built for continuous monitoring such as a sequential test, always-valid confidence intervals, or group-sequential boundaries. Repeatedly checking a fixed-horizon p-value against 0.05 pushes the real false-positive rate well above 5 percent.
Accepting a metric definition without asking about the denominator
Pin down the denominator, the eligibility filter and the time window before computing anything: conversion rate per session, per user, per eligible user and per new user are four different numbers with different behaviour. Restate the definition in one sentence and get agreement before you analyse.
SQL first, for a candidate whose queries have gone rusty
For someone who has spent the last year in notebooks, dashboards or modelling work and has not written raw SQL under time pressure. The first four days rebuild query fluency against a fixture you control and can verify by hand; the last three attach that fluency to the rest of the loop.
Day 1 — Build a fixture you can check answers against
- Create a local Postgres or SQLite database with four tables (users, sessions, events, orders) holding roughly 200 rows you generated yourself, so you know the contents well enough to predict every result.
- Deliberately seed the cases that break queries: a user with no sessions, a session with no events, two orders sharing a timestamp, a NULL in one join key, and one duplicated user row.
- Before writing any SQL, hand-compute five answers on paper (how many users placed at least one order, median orders per ordering user, and three others) and save them as the ground truth for the week.
Deliverable: A one-command seed script plus a text file of five hand-computed answers to grade every later query against.
Day 2 — Joins, filters and NULL semantics
- Answer "which users have no orders" three ways (LEFT JOIN with IS NULL, NOT EXISTS, NOT IN) and confirm that the NOT IN version returns zero rows once the subquery contains a NULL, because the comparison is never TRUE.
- Reproduce the LEFT JOIN that silently collapses to an inner join by putting a right-table predicate in WHERE, then fix it by moving the predicate into the ON clause, and record both row counts.
- Create a fan-out bug on purpose by joining orders to order_items and summing the order total, then correct it with a pre-aggregated subquery and explain in one line which table changed the grain.
Deliverable: One annotated .sql file holding the three join traps, each with the wrong result and the corrected result side by side.
Day 3 — Window functions and frames
- Write three window queries against the fixture: a running order total per user, the rank of each order within its user by value, and the day gap to that user's previous order, then check each against the day-one ground truth.
- Run ROW_NUMBER, RANK and DENSE_RANK over a column containing ties, print all three side by side, and write one sentence on when each is the correct choice.
- Switch one query from the default frame (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, which is what you get when ORDER BY is present and no frame is written) to ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and explain why the output differs only when the ORDER BY column has duplicates.
Deliverable: Three verified window queries plus a short note explaining the RANGE versus ROWS difference in your own words.
Day 4 — The four analytical query patterns
- Write a monthly retention grid: first order month per user, then months-since-first as the column, and verify that month zero equals the cohort size exactly.
- Sessionize the events table under a 30-minute inactivity rule using LAG plus a cumulative sum over a new-session flag.
- Build a four-step funnel that counts distinct users rather than events at each step, and state the rule you applied to a user who reaches step three without ever logging step two.
Deliverable: One file with the retention, sessionization and funnel patterns, each carrying a one-line note on the assumption it bakes in.
Day 5 — Write SQL the way you will have to write it live
- Set a 12-minute timer and solve three medium prompts in a plain editor with no execution and no autocomplete, then run them and tally syntax errors separately from logic errors.
- Narrate one solution aloud while writing it, stating the grain of each intermediate result (one row per user, one row per user-day) before you type its body.
- Rewrite your slowest solution as a CTE chain where every CTE name states its grain, and time yourself re-solving it from blank.
Deliverable: A recording of one narrated solution plus an error tally that separates syntax from logic.
Day 6 — One day for everything that is not SQL
- Write the preconditions of the two-sample t-test from memory, then check them: independent observations, and a difference in means whose sampling distribution is approximately normal, which at large sample sizes follows from the central limit theorem rather than from normality of the raw values.
- Write the difference between an odds ratio from logistic regression and a relative risk, and state the condition under which the two are close (low outcome prevalence).
- Prepare a 90-second answer to "how would you know this model is any good" that names the metric, the baseline you would beat, and the cost of the errors you care about.
Deliverable: One page of notes covering test preconditions, the odds-ratio caveat and the model-quality answer.
Day 7 — Full loop rehearsal
- Run a 45-minute mock with someone willing to interrupt: 20 minutes of SQL, 15 minutes defining a metric, 10 minutes on a past project.
- Re-solve from blank the two queries you were slowest on this week and compare the times against day five.
- Write a five-line answer to "walk me through a project" that puts a number in the first sentence and names the decision the work changed.
Deliverable: Mock feedback notes plus a timed project narrative you can deliver without reading it.
Frequently asked questions
Is this an official Wayfair interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Wayfair. Rounds and questions reflect what candidates have reported, not a process Wayfair has published, and they change over time. Confirm the current format and scope with your recruiter.
How technical is the online assessment, and what should I focus on?
The HackerRank assessment is highly technical and contains a mix of SQL, Python (using Pandas), and multiple-choice questions on statistics and machine learning. You should focus on speed and accuracy. Practice intermediate to advanced SQL (joins, window functions, group by) and standard Pandas operations like merging, filtering, and aggregating.
How much business knowledge do I need for the case study rounds?
You need a strong grasp of basic business and e-commerce metrics. You should understand concepts like revenue, gross margin, contribution margin, customer acquisition cost (CAC), and customer lifetime value (LTV). You must be able to think critically about how a technical model or product change affects these financial metrics.
What is the culture like for Data Scientists at Wayfair?
The culture is highly data-driven, collaborative, and fast-paced. There is a strong emphasis on ownership; data scientists are expected to drive projects from ideation to production. It is an environment where scientific rigor is highly valued, but speed-to-market and business impact are equally prioritized.
How long does the entire interview process take?
The process typically takes between 3 to 6 weeks from the initial HackerRank assessment to the final decision. However, this can vary based on candidate availability, team alignment, and hiring volume.
Keep practising
- Data Scientist question bank — cross-company practice.
- Interview preparation framework
- All interview guides