As a Data Scientist at Pubmatic, you will sit at the intersection of high-volume engineering, machine learning, and economic auction theory. Pubmatic is a leading sell-side platform (SSP) in the programmatic advertising industry, processing trillions of ad queries daily. In this role, your work directly influences real-time bidding (RTB) algorithms, publisher yield optimization, fraud detection, and click-through rate (CTR) estimation. The models you build and deploy must operate under strict low-latency constraints, meaning your theoretical designs must always align with high-performance engineering realities.
The impact of the data science team at Pubmatic is immediate and highly measurable. By developing sophisticated machine learning models, you help publishers maximize the value of their digital assets while ensuring advertisers reach their target audiences efficiently. This requires a deep understanding of statistical modeling, predictive analytics, and large-scale data processing systems.
To succeed as a Data Scientist here, you must possess a rare blend of mathematical rigor and practical engineering capability. You will work with massive, streaming datasets and collaborate closely with product and platform engineering teams to push models into production. It is a highly demanding but exceptionally rewarding environment where your algorithms directly drive millions of dollars in transactional value every single day.
Recruiter Phone Screen
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
Technical Assessment
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
Technical Interview Rounds
reportedMuch 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 to demonstrate
- 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
Virtual Onsite Panel
reportedA 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 to demonstrate
- 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
PracHub editorial advice for the preparation topics above.
Treating a bid as if it does not affect the price paid, under a first-price auction.
In a second-price auction the winner pays the runner-up's bid, so bidding true value is close to optimal and bid and price are usefully separable. Under first-price clearing, which is now the common case in open exchanges, the winner pays exactly what it bid, so raising the bid raises both the win probability and the cost of every win that would have been won anyway. A bid-increase experiment can therefore show more impressions, more conversions and worse profit simultaneously, and reading only the volume metrics will call it a success. The related second-order problem is that your own bid increase raises the clearing prices your control cells face, which contaminates the comparison unless the cells are separated by market.
Counting conversions without deduplicating across reporting sources and identity spaces.
The same purchase routinely arrives twice, once from a browser pixel and once from a server-side API, and the two reports carry different identifiers, so a naive count inflates conversions and deflates cost per action by the duplication rate. Deduplication depends on the advertiser populating a shared dedup_key correctly, which many do not, and the failure is silent because both rows look individually valid. The mirror-image error is under-counting: when a user clicks on a mobile app and converts in a desktop browser, the identity join fails and a real conversion is attributed to nothing, which makes the channel look worse than it is. Any conversion count reported without stating the dedup rule and the identity-match rate behind it should be treated as unverified.
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.
Crediting a treatment for regression to the mean
Selecting a group because it is extreme (lowest-engagement users, accounts having their worst month, the bottom decile of a score) moves that group's expected next-period value back toward the average even under no treatment, by exactly as much as the selecting measure is imperfectly correlated with its own later value. Compare against units that met the same selection rule and went untreated, or use two pre-periods so the bounce-back is visible before the intervention starts. A pre-post number on a group chosen for being extreme measures the selection rule, not the treatment.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
How do you calculate the conditional probability of an event, and how …
How do you calculate the conditional probability of an event, and how does Bayes' Theorem apply to classification?
Approach
- Sanity-check the answer against a simple bound or a simulated case.
- Write down the assumption the method needs before you use the method.
- 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?
- What sample size would you need to detect an effect half this size?
Define the mathematical difference between L1 and L2 regularization.
Define the mathematical difference between L1 and L2 regularization.
Approach
- Quantify uncertainty explicitly rather than reporting a point estimate alone.
- Translate the result into the decision it informs, in one plain sentence.
- Say what the estimate is of, and over what population it generalises.
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?
Explain the geometric interpretation of a derivative and how it is use…
Explain the geometric interpretation of a derivative and how it is used in gradient descent.
Approach
- Translate the result into the decision it informs, in one plain sentence.
- Say what the estimate is of, and over what population it generalises.
- Write down the assumption the method needs before you use the method.
Follow-up
- What sample size would you need to detect an effect half this size?
- How would you explain this result to someone who does not know statistics?
Walk through the mathematical formulation of logistic regression.
Walk through the mathematical formulation of logistic regression.
Approach
- Say how the offline result would be validated online before it is trusted.
- Check what information would not exist at prediction time, and exclude it.
- Set a baseline first, so any model has something honest to beat.
Follow-up
- Where could label leakage enter this setup?
- How would you choose the decision threshold, and who owns that choice?
Implement a basic search or sorting algorithm and explain its time and…
Implement a basic search or sorting algorithm and explain its time and space complexity.
Approach
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Say how the offline result would be validated online before it is trusted.
- Check what information would not exist at prediction time, and exclude it.
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?
Simulate bid shading profit under first-price auction clearing
auctions holds 200,000 backtest rows for one line_item_id: predicted_cvr (per impression), floor_price_cpm_usd (nullable when the floor is undisclosed), and best_competing_cpm_usd, the highest competing bid, observable only in this sample. Clearing is first price. The advertiser values a conversion at $40. For shading factors s from 0.50 to 1.00 in steps of 0.05, the submitted bid is s * 1000 * 40 * predicted_cvr and the line item wins when that bid clears both the floor and the best competing bid. Return win rate, spend, conversions and profit per thousand auctions, the profit-maximising s, and an uncertainty estimate for it.
Approach
- Separate what is deterministic from what is random before writing any sampling code. Given the bid, winning is deterministic and the price paid under first-price clearing is exactly the submitted bid, so the only stochastic element is whether a won impression converts. Use the closed form sum of predicted_cvr over wins for the expected conversion count and reserve Monte Carlo for the profit distribution, not the mean.
- Vectorise across s: build the bid vector once, then evaluate the 11 shading factors as numpy operations over the full array. A per-row Python loop over 200,000 rows by 11 factors is about two million iterations and turns a 3-second job into minutes.
- Make the win condition explicit and handle nulls deliberately: treat a null floor as no floor, require bid > best_competing_cpm_usd, and require bid >= floor_price_cpm_usd. Ties at exactly the floor behave differently from ties against a competitor, and the convention should be stated rather than inherited from a comparison operator chosen by accident.
- Compute profit per thousand auctions as (40 * conversions - sum of bid/1000 over wins) / n * 1000. Spend must use your own submitted bid, not the competing bid: under first-price clearing every inframarginal win, one you would have taken at a lower bid, now costs more, and that term is what creates an interior optimum.
- Get uncertainty by bootstrapping auction rows, recomputing the whole curve per replicate, and reporting the distribution of the argmax s rather than only a confidence band around the profit level. The decision uses the argmax, and it is far less stable than the profit curve it comes from.
- State the backtest's limit honestly: best_competing_cpm_usd was observed while you bid what you actually bid. If your change alters competitors' behaviour or triggers exchange-side floor adjustments, the counterfactual does not hold and the curve overstates the achievable gain.
Worked solution 35 min
- Precompute value_cpm = 1000 * 40 * predicted_cvr and floor_eff = floor_price_cpm_usd filled with -inf.
- For each s: bid = s * value_cpm; win = (bid > best_competing_cpm_usd) & (bid >= floor_eff); spend = bid[win].sum()/1000; expected conversions = predicted_cvr[win].sum().
- Profit per thousand auctions = (40 * conversions - spend) / n * 1000; assemble the 11-row curve with win rate = win.mean().
- Bootstrap: resample row indices with replacement 500 times, recompute the curve on each replicate, and collect the argmax s plus a percentile band on profit at the point-estimate optimum.
- Optionally draw Bernoulli(predicted_cvr) on won rows for one replicate set to show the profit distribution around the expectation, and confirm the sampled mean matches the closed form.
Follow-up
- Raising this line item's bid also raises the clearing price faced by another line item in the same account bidding on overlapping supply. How does that change the optimum, and how would you detect it in the logs?
- predicted_cvr over-predicts by 15% at the head of the distribution. Which way does the optimal s move, and roughly how far?
- How would you run this as a live test instead of a backtest, and what is the randomisation unit given that both arms draw on one budget?
How do you optimize a SQL query that joins multiple large tables?
How do you optimize a SQL query that joins multiple large tables?
Approach
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- State the window function and its partition and ordering out loud before writing it.
Follow-up
- How would you verify this result without re-running the same query?
- What breaks if events arrive late or out of order?
Explain the difference between a list and a tuple in Python, and when …
Explain the difference between a list and a tuple in Python, and when you would use each.
Approach
- State the window function and its partition and ordering out loud before writing it.
- Say which table is the grain you start from, and join outward from it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
Follow-up
- How would you verify this result without re-running the same query?
- How does the query change if the join becomes one-to-many?
Write a Python function to remove all duplicate elements from a list w…
Write a Python function to remove all duplicate elements from a list while maintaining the original order.
Approach
- Say which table is the grain you start from, and join outward from it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- Compute rates by summing numerator and denominator separately, never by averaging rates.
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?
Auction funnel stage counts and stage-to-stage drop-off
bid_request_log holds one row per (auction_id, line_item_id) evaluation, including line items that were considered and did not bid, with columns auction_id, request_ts, line_item_id, response_status (bid, no_bid, timeout, filtered), no_bid_reason and win_flag. ad_impression has impression_id, auction_id, line_item_id, served_ts, is_billable and ivt_status. ad_click has click_id, click_ts, impression_id (nullable), line_item_id (denormalised onto the click row when the click is written), ivt_status and is_billable. Return one row per line_item_id for a given UTC day with: auctions evaluated, auctions bid into, auctions won, impressions served, billable valid impressions, valid clicks, and the rate between each consecutive stage.
Approach
- State the grain of each table out loud before writing a join. bid_request_log is (auction_id, line_item_id); ad_impression is one row per impression; ad_click is one row per click event, carrying its own click_ts and a denormalised line_item_id plus a nullable impression_id, so one impression can produce several click rows and a click can be attributed to a line item without resolving its impression.
- Get the three auction-side stages from a single grouped scan of bid_request_log using COUNT(*) FILTER (WHERE ...). One pass, no self-joins, and the stages are guaranteed consistent with each other.
- Aggregate impressions and clicks in their own CTEs at their own grain, then LEFT JOIN the pre-aggregated results on line_item_id. Joining the raw tables together first multiplies rows at every step and the error compounds down the funnel.
- Decide what a click stage means and say so. COUNT(*) over ad_click counts click events; COUNT(DISTINCT impression_id) counts impressions that received at least one click, and silently drops the clicks whose impression_id is null. They are different numbers and the funnel reads differently under each.
- Say which clock the click stage is bucketed on. Filtering on click_ts places a click in the day it happened, which is not always the day its impression served: a click at 00:04 UTC on an impression from 23:58 the previous night lands in the next bucket, so a single-day CTR is approximate at the boundary. Bucketing clicks on the impression's served_ts instead removes that artefact but costs a join through impression_id and a decision about the null-impression_id clicks, which can then be counted in no bucket at all.
- Compute each rate against the stage immediately above it, with NULLIF on the denominator. The win-rate denominator is bids, not auctions evaluated.
Worked solution 20 min
- Write auctions AS (SELECT line_item_id, COUNT() AS evaluated, COUNT() FILTER (WHERE response_status = 'bid') AS bids, COUNT(*) FILTER (WHERE win_flag) AS wins FROM bid_request_log WHERE request_ts in the day GROUP BY 1).
- Write imp AS (SELECT line_item_id, COUNT() AS served, COUNT() FILTER (WHERE is_billable AND ivt_status = 'valid') AS clean FROM ad_impression WHERE served_ts in the day GROUP BY 1).
- Write clk AS (SELECT line_item_id, COUNT() AS clicks, COUNT() FILTER (WHERE impression_id IS NULL) AS unmatched FROM ad_click WHERE ivt_status = 'valid' AND is_billable AND click_ts in the day GROUP BY 1). This uses the click row's own line_item_id and click_ts, so the stage needs no join to ad_impression; the price of that is the midnight-boundary approximation above, which the unmatched count does not fix.
- LEFT JOIN the three CTEs on line_item_id and compute bids/evaluated, wins/bids, served/wins, clean/served and clicks/clean, each wrapped in NULLIF.
- Print the absolute counts beside the rates so a stage built on 40 rows is visible rather than hidden behind a percentage.
Follow-up
- This line item raised its bid, won more impressions, and its win rate fell. What mix shift produces that, and how do you show it from bid_request_log?
- Group the no-bid rows by no_bid_reason by hour. What shape tells you the budget exhausted early versus the targeting being too narrow all day?
- bid_cpm_usd, pre_shade_bid_cpm_usd and clearing_price_cpm_usd all sit on this table. What does the gap between them mean under first_price versus second_price clearing?
Pick the primary metric for a floor-price increase
A publisher raises the floor on a placement group by 20%. In bid_request_log you have floor_price_cpm_usd, response_status, no_bid_reason (including below_floor), win_flag and clearing_price_cpm_usd; in ad_impression you have billed_price_micros_usd, is_billable, viewability_status and ivt_status. Deliverable: the primary metric for judging the change, two guardrails, and a short argument for why effective CPM is the wrong primary here. Assume the change ships to a subset of placements, not to all supply.
Approach
- Say what the change does mechanically before choosing anything: bids below the new floor become
response_status = 'no_bid'withno_bid_reason = 'below_floor', so the won set after the change is a censored version of the won set before it. Every metric whose denominator is won impressions is now computed over a different population. - Kill eCPM as the primary with arithmetic, not adjectives. Suppose 1,000 impressions clear at $1.00 CPM and 1,000 at $3.00 CPM: revenue is $4.00, eCPM is $2.00. Censor the cheap tier and revenue is $3.00 while eCPM is $3.00 — revenue fell 25% and the metric rose 50%.
- Choose a denominator the change cannot move: revenue per thousand eligible bid requests, counted on distinct
auction_idinbid_request_log, filtered toivt_status = 'valid'on the revenue side. Unsold and no-bid opportunity stays in scope, which is exactly where the floor's cost shows up. - State the viewability precondition rather than hand-waving it. If you adjust revenue to viewable impressions only (50% of pixels in view for one continuous second, two for video), the adjustment is comparable across periods only while measurement coverage is stable — so carry the measurement rate as a guardrail, or report unadjusted and publish the rate alongside.
- Add the two diagnostic guardrails: fill rate (distinct auctions with
win_flag = TRUEover distinct eligible auctions) and thebelow_floorshare of no-bids. Together they tell you whether the revenue change came through price or through lost opportunity. - Because the change ships to a placement subset, hold the supply slice fixed — same
publisher_id,placement_id,ad_format,geo_countrymix — or decompose the movement into a price component and a fill component rather than comparing a shifted mix to itself.
Worked solution 20 min
- Work the two-tier numeric example end to end and write down both metrics before and after censoring.
- Write the eligible-RPM definition: SUM(billed_price_micros_usd)/1e6 over billable valid impressions, divided by COUNT(DISTINCT auction_id) of eligible requests, times 1000.
- Write the fill-rate and below_floor-share queries against bid_request_log, grouped by placement_id and hour.
- Predict the direction of each metric under the floor change, then state which combination of movements would make you recommend reverting.
Follow-up
- Eligible RPM is flat, fill fell 8%, and clearing price rose 9%. What do you tell the publisher?
- How would you estimate the revenue at stake before shipping the floor at all?
- Would your answer change if the placements cleared second price instead?
Set a stopping rule for a test that is read daily
A 21-day line-item test was sized for a fixed horizon. An analyst refreshes a dashboard every morning showing one primary metric, conversions per device, and six guardrails. On day 4 the primary shows p = 0.03 and the analyst wants to stop and ship. Give the type I error actually incurred by this monitoring pattern, propose a defensible stopping rule, and state how you would treat the six guardrails differently from the primary.
Approach
- Quantify the inflation rather than gesturing at it. Repeated fixed-horizon tests at a nominal 0.05 give roughly 14% type I error at 5 equally spaced looks and about 25% at 20. The naive 1 - 0.95^20 = 64% is wrong, because successive looks are strongly correlated partial sums of the same data.
- Offer the two valid families. A group-sequential plan with an alpha-spending function fixes the number and timing of looks in advance: O'Brien-Fleming spends almost nothing early (nominal p about 0.000005 at the first of five looks, 0.041 at the last), while Pocock spends a constant nominal 0.0158 at every look. Always-valid inference, such as a mixture sequential probability ratio test or a confidence sequence, permits unlimited looks at a cost of roughly 20-40% more sample at the planned horizon.
- Raise the day-4 problem that is not about alpha at all: the conversion window has not closed. Conversions keep arriving for click_window_days plus ingestion lag, so a day-4 read uses an immature numerator and is not the metric the test was sized on.
- Treat guardrails asymmetrically. One pre-registered primary metric needs no multiplicity correction. Guardrails are harm checks, and Bonferroni-correcting them lowers power to detect harm, which is conservative in the wrong direction; run each at 0.05 one-sided against a pre-set non-inferiority margin.
- If the team instead wants to claim a win on whichever of the seven metrics moves, that is a real multiplicity problem: control the false discovery rate with Benjamini-Hochberg, or use Bonferroni at 0.05/7 = 0.0071, and fix the rule before the test starts.
- Correct the estimate as well as the error rate. Conditional on stopping at the first boundary crossing, the observed effect is biased away from zero, so report a boundary-adjusted or median-unbiased estimate rather than the raw difference.
Follow-up
- Leadership wants a daily read regardless. Which of the two valid families do you pick, and what does it cost?
- One guardrail crosses at p = 0.04 on day 12. Do you stop?
- How does the conversion maturation curve change the earliest day the primary metric is even readable?
Post-click conversion rate dropped on mobile app supply only
Post-click conversion rate for one advertiser fell from 3.1% to 0.9% on device_type='mobile_app', with desktop and mobile_web flat. The metric is deduplicated conversion_event rows joined to ad_click on click_tracking_id within click_window_days, over valid billable ad_click rows, cohorted on click_ts. ad_click also has impression_id, device_id, landing_arrival_ts, ivt_status; conversion_event has source, device_id, click_tracking_id, dedup_key. The advertiser shipped a mobile SDK update that week. Decide whether conversions stopped happening or stopped being joinable, and recommend an action.
Approach
- Cohort correctly before anything else: restrict to click_ts dates older than click_window_days plus ingestion lag, so an immature window is not mistaken for a segment-specific drop.
- Split the single ratio into two consecutive steps — clicks to non-null landing_arrival_ts, and arrivals to joined conversions. A drop at the first step means users are not arriving, which is a real problem on the ad or landing side; a drop only at the second means they arrive and the join fails, which is instrumentation.
- If the break is at the join step, measure click_tracking_id null rate in conversion_event split by source and advertiser, by day. A step change on the mobile_sdk source against a flat browser_pixel source localises it to the advertiser's SDK release, and the break will be a single timestamp rather than a ramp.
- Rule out the denominator explanation explicitly, because it moves the metric the other way: rising sivt reclassification on mobile_app clicks removes rows from the denominator and would raise the rate, so an unchanged ivt_status distribution is a necessary check, not a formality.
- Establish that the conversions still exist by counting total conversion_event rows for the advertiser across the break, then recover the joinable population on device_id within the window and report both the recovered rate and the residual recovery gap from null device_id.
Follow-up
- What fraction of mobile_app clicks carry a null device_id, and what does that cap your recovery at?
- Would you restate the advertiser's reported CPA for the affected week, or footnote it, and what changes that decision?
- How would you monitor the joinable share as a first-class metric so this is caught the day it starts?
Instead of guessing where the week should go, day one measures it under a fixed rubric and allocates the remaining hours in proportion to the gaps. The method is deliberately rigid: the allocation is written down before any studying starts and is not renegotiated when a topic turns out to be unpleasant.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Diagnostic, scored before you study anything
- Sit a 100-minute timed diagnostic in four blocks: 30 minutes of SQL across three prompts, 25 minutes of short-answer statistics, 25 minutes on one modelling or case prompt, and 20 minutes delivering one behavioural story aloud.
- Score each block from 0 to 3 on a fixed rubric where 3 is correct and fluent, 2 is correct but slow or prompted, 1 is partially correct, and 0 is stuck, grading the output rather than how the attempt felt.
- Allocate the hours for days two to five roughly in proportion to 3 minus the score in each block, write the allocation down, and commit to not revising it midweek.
Deliverable: A scored rubric and a fixed hour allocation for the rest of the week.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Largest gap: find the boundary rather than the subject
- Break the weakest area into five named sub-skills (for query work: grain control, window frames, date arithmetic, set logic with NULLs, and reading a query plan) and rate each one, so the rest of the week targets a sub-skill instead of a subject.
- Solve three problems chosen to sit just above where the rating drops off, and for each write the first move you failed to make.
- Re-solve one of them from memory four hours later, on paper, with nothing open.
Deliverable: A five-item sub-skill map with the two blocking sub-skills circled.
Practice prompt ↗Practice prompt ↗Practice prompt ↗03Largest gap: drill the blocking sub-skill
- Do eight short repetitions of the same shape rather than eight different problems, so what you practise is the pattern and not the puzzle.
- Write the rule you now hold in one sentence, then test it against a case built to break it: a ranking function over a column with ties, or a two-sample test on observations that are obviously dependent.
- Have someone else read your one-sentence rule and find the precondition you left out.
Deliverable: One rule statement with its preconditions attached and one counterexample that would have caught the incomplete version.
Practice prompt ↗Practice prompt ↗04Second gap, plus maintenance on your strongest area
- Run the same sub-skill map and boundary protocol on the second-largest gap, compressed into half the day.
- Spend 25 timed minutes on your strongest area to stop it decaying, choosing the hardest problem you can still finish rather than an easy warm-up.
- Compare how the two areas fail: whether you lose time on recall, on setup, or on arithmetic, because the fix differs for each.
Deliverable: A second sub-skill map plus a one-line diagnosis of how each area fails you.
Practice prompt ↗Practice prompt ↗Worked solution ↗05The gap that is not a skill
- Record yourself answering one technical and one behavioural prompt, then count two things in the playback: how many seconds before your first clarifying question, and how many sentences you started without knowing where they ended.
- Rewrite your three most-used stock phrases into shorter versions, and practise saying "I do not know, here is how I would find out" without softening it into a guess.
- Deliver one answer again with a hard 90-second limit to force structure before detail.
Deliverable: Two recordings with a counted improvement in time-to-first-question.
Practice prompt ↗Practice prompt ↗06Retest under day-one conditions
- Sit the same 100-minute diagnostic structure with new prompts of comparable difficulty and score it on the identical rubric.
- Compare block by block, and for any block that did not move, change the method rather than adding hours: a block stuck at 1 usually means the practice was too varied, not too short.
- Write which single block you would still lose the offer on.
Deliverable: A second scored rubric placed next to the first, with one named remaining risk.
Practice prompt ↗Practice prompt ↗07Full loop under interview conditions
- Run a 60-minute mock covering the two blocks that moved least, with an interviewer instructed to interrupt and change direction.
- Write your recovery script for the moment you go blank: restate the question, state your assumption, name the first thing you would check.
- Reduce the week to the rule statements you wrote, each with its preconditions attached, then say every one of them out loud without reading it and cut any you cannot state in a single sentence, since a rule you have to reconstruct mid-answer will not survive being interrupted.
Deliverable: A one-page card holding the recovery script and only the rules you could state from memory.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Work that nobody used is a common and unflattering pattern in data careers, and interviewers probe for it. Have a story about an analysis that changed a decision, and be specific about how you got it in front of the person who could act. Also have one about work that went nowhere, with your reading of why.
How do you handle highly imbalanced datasets when training a binary cl…
How do you handle highly imbalanced datasets when training a binary classifier?
Approach
- Close with what you would do differently, concretely.
- Name the disagreement or constraint, and how you resolved it with evidence.
- 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?
- How did you know the outcome was caused by your change?
Defending a null incrementality result against a headline ROAS
Your geo holdout shows a retargeting line item's incremental conversions per $1,000 of spend are indistinguishable from zero. The same line item reports last-click ROAS of 8.3 and is the headline number in a renewal deck presented in six days. The account team believes your test is wrong; the advertiser has never questioned the 8.3. Deliverable: the internal case you make, the specific evidence you bring, the limits you concede, and the smallest reversible experiment you propose if your reading is rejected.
Approach
- The interviewer is probing whether you can hold an unpopular finding without turning it into a credibility fight, so open by granting that both numbers are computed correctly: last-click measures which touchpoint was nearest in time, the holdout measures what changed because of the spend. Framing attribution as 'wrong' converts a methodological point into a turf argument you will lose on relationship grounds.
- State the null as a bound rather than as zero. Report the minimum detectable effect the 20-market design could resolve and say 'we can rule out incremental ROAS above this value'. A null without an MDE is not a finding and is trivially dismissed as an underpowered test.
- Bring converging evidence from tables you already have, and say what each piece can and cannot show. Credit sensitivity: recompute the same conversion cohort under a second attribution_model, first-touch or even credit across in-window touchpoints, holding cohort and windows fixed, and report what share of the line item's credited volume survives; that bounds how much of the 8.3 is a property of the crediting rule rather than of the spend, and it is a sensitivity result, not a lift estimate. Harvesting signature: the share of retargeting-credited conversions whose user already had an earlier impression, click or site session inside click_window_days, together with the distribution of conversion_ts minus click_ts, where a heavy mass inside a few minutes is consistent with an ad served into a session that was already converting.
- Quantify both error directions before recommending anything: the spend at risk if you are right and ignored, and the renewal revenue at risk if you are wrong and act. This is what separates a defensible position from an ideological one.
- Propose the reversible version rather than the shutdown: a 20% budget reduction in half the matched markets for six weeks, powered against the MDE you just computed, with the analysis window extended past the flight by the click window plus ingestion lag.
Follow-up
- The account lead says telling the advertiser their favourite channel does nothing will cost us the renewal. How do you respond without either caving or escalating?
- What specific evidence would change your mind about this line item?
- How do you handle it if the budget-down test also comes back underpowered?
Claiming impact for three projects with honest counterfactuals
You are writing a performance self-review. Over two quarters you shipped a bid-shading recalibration, a rewrite of the click-through-rate query that fixed an invalid-traffic filter applied to only one side of the ratio, and an incrementality test that led to a line item being paused. Deliverable: for each, the number you would claim, the counterfactual you claim it against, and the portion of credit that belongs to someone else. One of the three has no defensible dollar figure. Say which, and what you claim instead.
Approach
- The interviewer is probing whether you apply the same causal standard to your own work that you apply to an advertiser's, so write the counterfactual for each claim before the number: what would the metric have been over the same period without this work?
- For the shading recalibration, compare clearing price and profit on won impressions at matched supply mix across exchange_id, ad_format, device_type and geo_country, and report the profit change rather than the win-rate change; under first-price clearing a higher win rate can accompany worse profit.
- For the query fix, claim the magnitude of the bias removed rather than a revenue number: the gap between the old rate, which filtered invalid traffic on the numerator only, and the corrected symmetric rate, plus the decision that was being made on the wrong figure.
- For the incrementality test, claim the decision, not the savings. The paused budget's fate was never measured, so any dollar figure would assume that money vanished rather than moved. This is the item with no defensible number.
- Name specific collaborators and what they contributed, and pre-empt the obvious challenge by stating the confound you know about, such as seasonality or supply mix drift, and the bound you put on it.
Follow-up
- Your manager points out the paused line item's spend simply moved to another line item. Does your claimed impact survive?
- How do you claim credit for work whose value is a bad decision that did not happen?
- 01
How do you handle highly imbalanced datasets when training a binary classifier?
- 02
Your geo holdout shows a retargeting line item's incremental conversions per $1,000 of spend are indistinguishable from zero. The same line item reports last-click ROAS of 8.3 and is the headline number in a renewal deck presented in six days. The account team believes your test is wrong; the advertiser has never questioned the 8.3. Deliverable: the internal case you make, the specific evidence you bring, the limits you concede, and the smallest reversible experiment you propose if your reading is rejected.
- 03
You are writing a performance self-review. Over two quarters you shipped a bid-shading recalibration, a rewrite of the click-through-rate query that fixed an invalid-traffic filter applied to only one side of the ratio, and an incrementality test that led to a line item being paused. Deliverable: for each, the number you would claim, the counterfactual you claim it against, and the portion of credit that belongs to someone else. One of the three has no defensible dollar figure. Say which, and what you claim instead.
Is this an official Pubmatic interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at Pubmatic. Rounds and questions reflect what candidates have reported, not a process Pubmatic has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult is the Data Scientist interview at Pubmatic?
The interview is generally rated as difficult. While the coding requirements are often straightforward, the mathematical, statistical, and algorithmic theory questions are highly rigorous and require deep preparation.
PracHub interview research ↗What is the typical timeline for the interview process?
The entire process is relatively quick, often taking between two to four weeks. Recruiters are highly responsive, and technical rounds are scheduled in rapid succession once you pass the initial screens.
PracHub interview research ↗Do I need prior experience in ad-tech to apply?
While prior ad-tech experience is a significant advantage due to the specialized nature of auction dynamics and RTB, it is not a strict requirement. Strong foundational skills in machine learning, statistics, and scale are highly valued.
PracHub interview research ↗Is there a coding round in the interview process?
Yes, you should expect at least one coding round, which may focus on basic data structures, Python manipulation, or SQL. However, the primary focus of the technical rounds remains on machine learning theory and math.
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