DoorDash Applied Scientist (Junior Level) Interview Preparation Guide
DoorDash's interview process for applied ML roles combines recruiter screening, phone-based technical assessments (coding and problem-solving), and onsite rounds evaluating algorithmic skills, software engineering depth, ML system architecture thinking, and cultural fit. For junior level, expect 5-6 total rounds spanning 4-6 weeks, with emphasis on demonstrating solid fundamentals, hands-on implementation ability, and understanding of end-to-end ML systems in production.
Interview Rounds
Recruiter Screening
What to Expect
Initial phone or video conversation (30-45 minutes) with a recruiter to assess background, interest in DoorDash, and role fit. Recruiters focus on understanding your applied ML experience, systems you have worked on, and whether you have owned models or features end-to-end (deployment, monitoring, iteration). This round gates entry to technical interviews.
Tips & Advice
Prepare a 2-minute narrative connecting your ML background to DoorDash's marketplace challenges. Be specific about one project where you owned the full lifecycle—from modeling to production monitoring. Articulate why DoorDash's problem domain excites you (e.g., real-time personalization, logistics optimization, fraud detection). Research DoorDash's marketplace structure and ask thoughtful questions. For junior level, emphasize learning velocity and eagerness to own increasingly complex pieces.
Focus Topics
Learning Trajectory & Growth Mindset
Discuss how you've grown technically in previous roles, skills you've developed, and how you approach learning unfamiliar domains. For junior level, emphasize ability to ramp quickly with guidance.
Practice Interview
Study Questions
Why DoorDash & Marketplace Understanding
Articulate what excites you about DoorDash's specific problems: real-time delivery optimization, supply-demand balancing, fraud prevention, merchant quality, Dasher incentives, or recommendations. Show familiarity with three-sided marketplace dynamics.
Practice Interview
Study Questions
End-to-End Project Ownership
Prepare a detailed walkthrough of a model or feature you owned from conception through production. Include problem definition, data collection, feature engineering, modeling, evaluation, deployment challenges, and post-launch monitoring.
Practice Interview
Study Questions
Background & Applied ML Experience
Articulate your ML background with emphasis on hands-on projects, not just coursework. Highlight one or two systems where you moved beyond notebooks—training, evaluation, deployment, and monitoring.
Practice Interview
Study Questions
Technical Phone Screen – Coding Round 1 (Algorithmic Clarity)
What to Expect
60-minute remote coding interview (HackerRank CodePair) evaluating algorithmic problem-solving, code clarity, and software engineering fundamentals. You will solve 1–2 LeetCode-style problems, typically involving graphs (routing, batching), dynamic programming, or string/array manipulation. Focus is on correctness, edge-case handling, and explaining your approach before coding.
Tips & Advice
Start by clarifying the problem and discussing approach before writing code. Walk through edge cases and time complexity explicitly. For junior level, interviewers expect correct solutions to medium-difficulty problems, not optimality. Use clean variable names and modular code. If stuck, talk through your reasoning; interviewers prefer to see problem-solving thought process over silence. Practice on Interview Query's problem library to match DoorDash's style and difficulty.
Focus Topics
Edge Case & Error Handling
Identify and handle boundary conditions: empty inputs, single elements, duplicates, negative numbers, and invalid states. Write defensive code and discuss assumptions.
Practice Interview
Study Questions
Dynamic Programming Fundamentals
Solve classic DP problems: longest common subsequence, coin change, unbounded knapsack, or optimal substructure problems. Master the DP pattern: identify overlapping subproblems, define state, and build bottom-up or memoized solutions.
Practice Interview
Study Questions
String & Array Manipulation
Handle problems involving pattern matching, sorting, two-pointer techniques, and sliding windows. Examples: longest substring without repeating characters, merge intervals, rotate array.
Practice Interview
Study Questions
Time & Space Complexity Analysis
Articulate big-O notation for your solution, discuss trade-offs between time and space, and explain how your solution scales under large inputs. For junior level, demonstrate ability to recognize and explain complexity clearly.
Practice Interview
Study Questions
Graph Algorithms (Routing & Batching)
Solve problems involving shortest path, minimum spanning tree, or graph traversal. DoorDash uses these for delivery routing, order batching, and location optimization. Practice BFS, DFS, Dijkstra, and union-find.
Practice Interview
Study Questions
Technical Phone Screen – Coding Round 2 (Software Design)
What to Expect
60-minute remote coding interview focusing on software design, stateful services, and practical implementation. You may solve a system-design-adjacent coding problem (e.g., design a cache, distributed counter, or event queue) or implement a feature with multiple components. Emphasis is on clean architecture, separation of concerns, and reasoning about trade-offs.
Tips & Advice
Before coding, ask clarifying questions about requirements, constraints, and scale. Sketch a high-level design on the whiteboard or doc: components, interfaces, data structures. For junior level, focus on clarity and correctness over advanced patterns. Discuss trade-offs (e.g., consistency vs. availability) at a conceptual level. Handle failure gracefully: what happens if a service is slow or unavailable? Test edge cases and discuss monitoring hooks.
Focus Topics
Error Handling & Graceful Degradation
Design systems that fail safely: circuit breakers, timeouts, fallbacks, and retry logic. Discuss observability hooks for debugging failures.
Practice Interview
Study Questions
Concurrency & Thread Safety Basics
Understand race conditions, locks, and thread-safe data structures. Know when to use synchronization and the cost of contention. Practice with simple concurrent problems.
Practice Interview
Study Questions
API & Interface Design
Design clean, composable APIs: identify inputs, outputs, error cases, and side effects. Use design patterns (factory, observer, adapter) when appropriate. For junior level, focus on clarity and avoiding over-engineering.
Practice Interview
Study Questions
Stateful Service Design
Design services that maintain state: caches, queues, databases. Understand consistency models, concurrency, and failure modes. Examples: implement a thread-safe cache with eviction, or a simple message queue with ordering guarantees.
Practice Interview
Study Questions
Onsite – ML System Design Round
What to Expect
60-90 minute whiteboard or shared-doc discussion evaluating end-to-end ML architecture thinking. You will be asked to design a system for a DoorDash use case: ETA prediction, fraud detection, demand forecasting, merchant ranking, or similar. Interviewers expect you to discuss training pipelines, feature stores, real-time inference, monitoring, and rollback strategies. Emphasis is on reasoning about trade-offs, not memorizing systems.
Tips & Advice
Start by clarifying the business problem: what are we optimizing for, who are the stakeholders (consumers, merchants, Dashers), and what are the constraints (latency, cost, accuracy)? Sketch a simple end-to-end flow: data collection → feature engineering → training → serving → monitoring. Discuss feedback loops and label bias. For junior level, focus on understanding each component's purpose and key trade-offs, rather than deep architectural complexity. Ask about scale and constraints to scope realistically. Be ready to explain how you'd validate labels, handle data drift, and roll back safely if the model fails.
Focus Topics
Trade-Offs: Accuracy vs. Latency, Cost, Complexity
Reason about practical trade-offs: when is a simple model better than a complex one? When can you afford to retrain? What's the cost of waiting for features? For junior level, demonstrate structured thinking about constraints.
Practice Interview
Study Questions
Feedback Loops & Label Bias
Understand how model predictions influence future data: positive feedback loops, selection bias, and measurement bias. Discuss de-biasing strategies and causal inference basics.
Practice Interview
Study Questions
Monitoring, Alerting & Model Drift Detection
Design layered monitoring: input distribution shifts, prediction drift, calibration, latency, error budgets. Discuss alert thresholds, automated rollback, and how to separate data issues from model issues. Understand label validation and production label delays.
Practice Interview
Study Questions
Real-Time Inference Architecture
Design serving systems for low-latency prediction: in-memory caches, model servers (TensorFlow Serving, KServe), batching strategies, and fallbacks. Discuss latency budgets and cost trade-offs.
Practice Interview
Study Questions
Feature Engineering & Feature Stores
Design features for a DoorDash domain (ETA, fraud, demand). Discuss feature compute (batch vs. real-time), storage, and versioning. Understand train-serve skew and cold-start problems.
Practice Interview
Study Questions
End-to-End ML Pipeline Architecture
Design the full lifecycle: data ingestion, feature engineering, model training, serving, and monitoring. Identify bottlenecks and discuss orchestration (Airflow, Kubernetes). For junior level, emphasize understanding each stage and why it matters.
Practice Interview
Study Questions
Onsite – ML Concepts & Modeling Judgment Round
What to Expect
60-minute discussion evaluating modeling expertise, feature interpretation, and judgment on ML decisions. Interviewers will ask questions like: 'How would you handle high-cardinality features?' 'Explain logistic regression coefficients in production.' 'How would you approach a cold-start problem?' These test your ability to explain model behavior, make design choices under constraints, and think critically about trade-offs.
Tips & Advice
Be prepared to explain fundamental models (linear regression, logistic regression, tree-based methods, embeddings) in intuitive and mathematical terms. For DoorDash problems, connect model choices to business constraints: interpretability for fraud scoring, latency for real-time ranking, stability for supply forecasting. Discuss real-world challenges: class imbalance, missing data, evaluation metrics under distributional shift. For junior level, focus on demonstrating solid fundamentals and awareness of practical pitfalls. Use concrete examples from your experience.
Focus Topics
Evaluation Metrics & Production Safety
Design metrics that reflect real-world impact: not just model accuracy but downstream effects (cancellation rate, Dasher earnings, customer satisfaction). Use guardrail metrics to prevent negative surprises.
Practice Interview
Study Questions
Handling Class Imbalance & Evaluation Metrics
Understand when accuracy is misleading (e.g., fraud detection, delivery failure prediction). Choose metrics: precision, recall, F1, AUC, or custom business metrics. Discuss threshold selection, cost-weighted losses, and evaluation under distribution shift.
Practice Interview
Study Questions
Cold-Start Problems & Feature Availability
Handle new users, merchants, items, or locations with no historical data. Strategies: content-based features, collaborative filtering with fallbacks, or rule-based policies. Discuss trade-offs between personalization and reliability.
Practice Interview
Study Questions
High-Cardinality Feature Encoding
Compare approaches: hashing, target encoding, learned embeddings, frequency bucketing. Discuss leakage risks, cold-start problems (new merchants, new locations), and serving costs. Evaluate stability when categories arrive daily.
Practice Interview
Study Questions
Model Interpretability for Business Applications
Explain logistic regression coefficients, one-hot encoding, baseline categories, and log-odds interpretation. Discuss why interpretability matters for risk scoring and policy decisions (e.g., fraud guardrails, merchant quality). Understand multicollinearity, regularization effects on coefficients, and actionable insights from coefficients.
Practice Interview
Study Questions
Onsite – Behavioral & Values Fit Round
What to Expect
45-60 minute interview evaluating collaboration, accountability, learning, and alignment with DoorDash values. Expect behavioral questions (STAR format): 'Tell me about a time you shipped a model that caused an incident.' 'Describe a project where you influenced a technical decision.' 'How do you handle ambiguity and changing requirements?' Interviewers assess how you work in teams, take ownership, and navigate real-world constraints.
Tips & Advice
Use the STAR method (Situation, Task, Action, Result) with concrete details. For junior level, emphasize learning from mistakes, collaborating with mentors, and taking ownership of small-to-medium scoped work. DoorDash values calm, pragmatic problem-solving—avoid heroics. Quantify impact where possible (e.g., 'reduced latency from 500ms to 200ms', 'improved fraud detection precision by 15%'). Prepare stories about shipping incomplete solutions under time pressure, handling feedback, and growing as an engineer. Ask thoughtful questions about DoorDash's culture, learning opportunities, and how the team collaborates.
Focus Topics
Curiosity & Initiative
Discuss a problem you identified proactively (not assigned) and how you approached it. Show you think beyond assigned tasks and ask good questions.
Practice Interview
Study Questions
Pragmatism & Shipping Under Constraints
Tell a story where you had to trade accuracy for speed, simplicity, or cost. Explain your reasoning and the outcome. For junior level, show you understand business context and prioritization.
Practice Interview
Study Questions
Learning & Growth from Mistakes
Describe a technical mistake, how you diagnosed it, and what you learned. Discuss process improvements to prevent recurrence. Show humility and growth mindset.
Practice Interview
Study Questions
Collaboration & Communication
Share an example of working with engineers, data engineers, or product managers to ship something. Discuss how you aligned on requirements, handled disagreements, and iterated. For junior level, emphasize listening and incorporating feedback.
Practice Interview
Study Questions
Ownership & Accountability in Production
Prepare a story where your model, feature, or analysis directly impacted production. Include how you monitored it, what went wrong (if anything), your root-cause analysis, and the fix. For junior level, focus on learning and improved processes, not heroics.
Practice Interview
Study Questions
Frequently Asked Applied Scientist Interview Questions
How do you keep track of the decisions made during a cross-functional project so the reasoning behind them doesn't get lost or re-litigated later?
Sample Answer
Direct answer
Keep a single, easy-to-find decision log tied directly to the work it affects: what was decided, the options considered, the reasoning, and who owns it, updated by whoever is making the decision at the moment it is made, not reconstructed later from memory.
Structured elaboration
What belongs in an entry
A short, consistent structure works better than a long one, because people will actually fill it out: a title, the date, who owns it, the context in one or two sentences, the options considered with their trade-offs, the decision itself, and the reasoning behind it in a few bullet points.
Where it lives
The log needs to be one discoverable place, linked from the tickets, docs, or roadmap items it affects, not scattered across meeting notes and chat threads. A shared doc or wiki page with a simple table works; the tool matters less than the discipline of always linking to it.
Who keeps it current
The person who owns the decision, not a rotating scribe with no stake in it, writes or finalizes the entry, ideally right after the decision is made, while the reasoning is still fresh and easy to state accurately.
How it gets used afterward
In retrospectives, revisit decisions that affected the outcome and check whether the original assumptions held. For onboarding, a short list of the most consequential recent decisions gives a new team member the context that would otherwise take weeks of osmosis to pick up.
Worked example
A team is deciding between two ways to notify users of an event: a push notification versus an in-app banner. The entry, once decided, looks like this: title, "Notification channel for event alerts"; date and owner, the decision owner's name and the date; context, users were missing time-sensitive alerts under the current in-app-only approach; options considered, push notification (faster delivery, requires a new permission prompt), in-app banner only (no new permission needed, slower to be seen), and both channels (best coverage, more engineering and support surface); decision, push notification with an in-app banner as a fallback for users who decline the permission; reasoning, the delay in the in-app-only approach was the specific problem being solved, and the fallback covers users who opt out.
Anyone who later asks why the team does not just use an in-app banner, since it is simpler, can read this entry and see the trade-off was already considered, rather than re-litigating it from scratch.
Trade-offs and pitfalls
A log nobody updates is worse than no log: it creates false confidence that the reasoning is captured somewhere, while actually going stale. The fix is keeping entries short enough that updating one takes minutes, rather than requiring a formal write-up every time.
A log can also be used as a weapon later, such as insisting a past decision still holds in a situation where circumstances genuinely changed and revisiting was the right call. The log should record reasoning, not lock in a decision forever; a review date or a note on when to re-evaluate keeps it a living reference instead of a trap.
Tell me about a time you discovered a significant data-quality problem only after a model was in production. Describe the steps you took to investigate and isolate the issue, how you communicated with stakeholders, how you remedied the production data pipeline, and what long-term controls you implemented to prevent recurrence.
Sample Answer
Situation & Task
I discovered a production-quality drop when a fraud-detection model's precision fell 18% two weeks after deployment. Business alerted because false positives spiked and operations saw increased manual reviews.
Investigation & Isolation (Action)
- Reproduced issue locally with a recent snapshot of production features.
- Ran feature-distribution checks and found a categorical feature’s cardinality had increased — a new payment-provider code appeared and was mapped to the default “other” bucket during featurization.
- Traced upstream: a partner changed their API response (new enum value) so our ETL parsed it as null. I confirmed via logs and raw message samples in S3 and by comparing schema evolution in the data catalog.
Remediation (Action)
- Short-term: rolled back model to the previous version and applied a hotfix in the featurizer to treat unseen enums explicitly, reducing misclassification immediately. Deployed a backfill job for the last 7 days to rebuild affected features and retrained the model with corrected data.
- Long-term controls: implemented schema validation with Great Expectations checks at ingestion, added an alert for categorical cardinality drift, and added a CI test that simulates unseen enums. Created a data contract with the partner and set up weekly contract-validation jobs.
Communication & Outcome (Result)
- Sent a concise incident summary and remediation plan to product, ops, and the partner within 2 hours, followed by a postmortem with timeline, root cause, and action items. Precision recovered to pre-incident levels; manual reviews dropped 40%. Lessons: enforce schema contracts, add automated checks, and include robustness for unseen categories in model inputs.
Define shadow traffic (shadow testing) and explain how you'd use it to validate a new ranking model without affecting user-facing responses. What are the benefits, and what operational or privacy pitfalls should you watch for?
Sample Answer
Direct answer
Shadow traffic means forking real production requests to a candidate model that scores them without its response ever reaching the user: it validates real-world behavior with zero user-facing risk, at the cost of not being able to observe how users would actually react to the candidate's different predictions.
Structured elaboration
The core mechanism: the serving layer duplicates each incoming request, sends one copy to the currently-serving model (whose response goes to the user, as normal) and one copy to the shadow candidate (whose response is logged and compared, but discarded rather than served). This gives you genuine production-scale, production-distribution validation: not a sampled offline test set, but literally today's real traffic: without any risk of a bad candidate actually harming a user.
Benefits: catches problems an offline evaluation set can't (a candidate that errors or times out on a specific real-world input pattern your offline set didn't happen to include), at the full scale and true distribution of production traffic, with zero blast radius if something's wrong.
Operational pitfalls: shadow traffic still consumes real compute: running two models against every request roughly doubles serving-side compute cost for the duration of the shadow test, which needs budgeting, not an afterthought. Privacy pitfalls: the candidate model is processing real user data even though its output is discarded: any data-handling or retention policy that applies to a genuinely serving model still applies here (the fact that the response isn't shown to the user doesn't exempt the request from privacy obligations around processing it).
Worked example
For validating a new ranking model: fork live search traffic to the candidate, log its ranked results alongside the currently-serving model's, and compare offline (rank correlation, overlap in top-K results, latency) without ever showing the candidate's ranking to a real searcher: this catches a candidate that, say, returns wildly different (and plausibly worse) top results for a specific query pattern that the offline evaluation set happened not to cover, before any user ever sees it.
Trade-offs & pitfalls
Shadow testing's structural limitation is that it can only validate the model's OUTPUT given real inputs, never how a real user would have RESPONDED to a different output: a ranking model whose shadow-tested results look statistically reasonable can still turn out to change user behavior in a way only a real canary (where users actually see and react to the new ranking) would reveal. Shadow testing is the right FIRST gate specifically because it's cheap-risk, not because it's sufficient on its own.
You are deciding between an unsupervised anomaly-detection method (for example Isolation Forest) and a supervised classifier trained on imbalanced labels for a rare-event detection problem. What criteria (label availability and quality, novelty of the pattern you are trying to catch, operational constraints) would lead you to favor one approach over the other, and how would you combine both in production?
Sample Answer
Direct answer
Favor an unsupervised anomaly detector when you have little or no reliable labeled data for the rare class and are trying to catch NOVEL patterns you haven't seen before; favor a supervised classifier when you have enough labeled examples of the specific pattern you're targeting and want to optimize directly for catching more of exactly that pattern.
Structured elaboration
Decision criteria:
- Label availability and quality: supervised classification needs enough labeled positives to learn a real decision boundary; below some threshold (a handful to a few dozen confirmed examples), a supervised model has too little signal, and an unsupervised "what does normal look like" approach makes better use of the abundant unlabeled negative data instead.
- Novelty of the pattern: if attackers, fraudsters, or failure modes evolve and you need to catch things you've never labeled before, unsupervised approaches generalize to novel patterns better, since they're not fit to any specific known positive shape; a purely supervised classifier trained only on past labeled fraud will systematically miss fraud that looks different from what it learned.
- Operational constraints: a supervised classifier gives you a single, directly-optimized precision/recall trade-off you can tune; an unsupervised anomaly score requires you to separately calibrate what threshold on "anomalousness" corresponds to an acceptable alert volume, which is less direct but doesn't require labels to set up in the first place.
In production, these are rarely either/or: run both and combine, using the unsupervised score as an additional FEATURE fed into the supervised model (so the supervised model gets to learn how much to trust the anomaly signal), or run the unsupervised detector as a first-pass filter over a huge volume of events before a more expensive supervised model or human reviewer looks at the smaller flagged subset.
Worked example
For a new fraud pattern with only 3 confirmed cases so far, an unsupervised Isolation Forest trained on the abundant "normal" transaction data can flag transactions that look statistically unusual along any dimension, without needing to have seen this exact pattern before; a supervised classifier trained on those same 3 examples would essentially be memorizing 3 points, with almost no ability to generalize to a fourth, differently-shaped case.
Trade-offs and pitfalls
The common mistake is picking one approach permanently rather than revisiting the choice as labels accumulate: what starts as an unsupervised-first system, appropriate when labels are scarce, should graduate toward a supervised or hybrid approach once enough confirmed labels exist to make supervised learning worthwhile, since a well-tuned supervised classifier will generally outperform an unsupervised one on the SPECIFIC pattern it has plenty of labels for.
You have a list of service records: [{"name": "svc1", "latency": 123}, ...]. Implement a function in Python to order services by descending latency such that services with equal latency keep their original relative order. Explain what makes a sort "stable" and why that property matters when a caller later sorts by a second key (e.g. latency then name).
Sample Answer
Direct answer
Sort with sorted(services, key=lambda r: r["latency"], reverse=True). Python's built-in sort (Timsort) is guaranteed stable, and reverse=True is implemented as a stable reversal of the comparison direction rather than reversing the whole list afterward, so two services with equal latency keep their original relative order in the result exactly as they had it in the input.
Structured elaboration
What "stable" means
A stable sort guarantees that when two elements compare EQUAL under the sort key, their relative order in the output matches their relative order in the input. An unstable sort makes no such guarantee: it may (in an implementation-dependent way) reorder elements that compare equal.
Why stability matters when a caller later sorts by a second key (the question's explicit ask)
Stability is what makes "sort by the less important key first, then stably sort by the more important key" equivalent to sorting by the combined (more-important-key, less-important-key) pair in one pass. You sort by the LEAST significant key first, then by the MOST significant key last; because each stable sort preserves ties from the previous pass, the final order is correct for both keys simultaneously. The worked example below does exactly this: sort by name first, then stably sort by latency descending, producing "latency descending, ties broken by name ascending" without writing a composite comparator by hand. If the underlying sort were not stable, this two-pass trick would not be safe. Every tiebreaker would have to be baked into one comparator up front, since a later pass could not be trusted to leave an earlier pass's ordering intact.
Worked example
Full runnable code (defines the service records, sorts them, and checks tie order directly rather than just asserting it), executed with python3 s80.py:
services = [
{"name": "svc1", "latency": 123},
{"name": "svc2", "latency": 200},
{"name": "svc3", "latency": 123},
{"name": "svc4", "latency": 50},
{"name": "svc5", "latency": 200},
]
sorted_desc = sorted(services, key=lambda r: r["latency"], reverse=True)
print("input order:", [(s["name"], s["latency"]) for s in services])
print("sorted desc :", [(s["name"], s["latency"]) for s in sorted_desc])
group200 = [s["name"] for s in sorted_desc if s["latency"] == 200]
group123 = [s["name"] for s in sorted_desc if s["latency"] == 123]
print("latency=200 group order:", group200, "-> stable:", group200 == ["svc2", "svc5"])
print("latency=123 group order:", group123, "-> stable:", group123 == ["svc1", "svc3"])
# Two-key composite: sort by the least significant key first (name), then
# stably sort by the most significant key (latency, descending).
by_name = sorted(services, key=lambda r: r["name"])
composite = sorted(by_name, key=lambda r: r["latency"], reverse=True)
print("latency desc, name asc tiebreak:", [(s["name"], s["latency"]) for s in composite])
Output (actual run), five pinned service records with two separate latency ties:
input order: [('svc1', 123), ('svc2', 200), ('svc3', 123), ('svc4', 50), ('svc5', 200)]
sorted desc : [('svc2', 200), ('svc5', 200), ('svc1', 123), ('svc3', 123), ('svc4', 50)]
latency=200 group order: ['svc2', 'svc5'] -> stable: True
latency=123 group order: ['svc1', 'svc3'] -> stable: True
svc2 appeared before svc5 in the input (both latency 200), and svc2 still appears before svc5 in the descending-sorted output, directly confirming that reverse=True did not disturb tie order. The same holds for the svc1/svc3 tie at latency 123.
The same run also prints the two-key composite demonstration (sort by name, then stably sort by latency descending), from the code above:
latency desc, name asc tiebreak: [('svc2', 200), ('svc5', 200), ('svc1', 123), ('svc3', 123), ('svc4', 50)]
With these particular five records the name-based tiebreak happens to reproduce the same order as the latency-only sort (since svc2 < svc5 alphabetically and svc1 < svc3 alphabetically as well), which is a coincidence of this input, not a general property; the two-pass technique is what's being demonstrated, not this specific input's tie outcome.
Trade-offs and pitfalls
- A common mistake is assuming
reverse=Truereverses tie order too. In Python it explicitly does not; always verify this for whatever language or library is actually in use, since not every standard sort guarantees stability by default, and that needs to be checked rather than assumed to transfer across platforms. - If the goal is "latency descending, then name descending" (both descending), stability by itself does not give you that for free with the two-pass technique above; you would either negate the secondary key directly (workable for numbers, awkward for strings) or build a single composite key with an explicit reverse-ordering wrapper for the secondary field.
- Relying on stability to chain multiple sort passes only works if EVERY pass in the sequence is genuinely stable. Mixing in a single non-stable sort anywhere in the chain silently breaks the ordering guarantee for every key sorted before it, not just the pass where the non-stable sort was used.
Design a simple feature-store prototype appropriate for a small ML team (not a hundred-million-user platform). Enumerate the core components you'd actually need and why, the minimum metadata to capture, and a basic versioning-and-backfill approach that keeps training reproducible without over-engineering the platform.
Sample Answer
Direct answer: A small ML team's feature-store prototype needs the same conceptual components as a large-scale one (ingestion, offline and online storage, a lightweight registry, an SDK), just built with dramatically less operational overhead, prioritizing "good enough and maintainable by a small team" over the generality a hundred-million-user platform would need.
Structured elaboration:
For a small team, a reasonable minimal design: a single, simpler offline store (a standard warehouse table is often enough, no need for a specialized data lake architecture), a similarly simple online store (a managed key-value service rather than a custom-built, heavily-tuned cluster), a lightweight registry (even a well-maintained spreadsheet or a simple metadata table can work at this scale, rather than a full metadata service), and an SDK that's a thin wrapper enforcing the training/serving consistency discipline discussed elsewhere in this topic, without needing the elaborate access-control and multi-tenancy machinery a large shared platform requires.
Minimum metadata to capture, even at small scale: owner, a link to the transformation code, and a basic freshness expectation; this is a much shorter list than a large enterprise catalog would carry, but omitting it entirely (even for a small team) reintroduces the same "nobody remembers why this feature exists" problem at a smaller scale.
Versioning and backfill at this scale can be much simpler than the large-scale design: a basic append-only versioned table (rather than a fully general versioning service) is often sufficient to keep training reproducible, as long as the discipline of never silently overwriting a previous version is maintained.
Worked example: A five-person ML team building their first shared feature infrastructure doesn't need multi-region replication, tiered caching, or a dedicated platform team; a managed cloud key-value service for online serving, a standard warehouse table for offline, and a shared metadata spreadsheet with a lightweight review step before a new feature ships captures most of the reproducibility and reuse benefit a much larger platform would provide, at a fraction of the build and operational cost.
Trade-offs and pitfalls: Over-engineering this for a small team (building the full hundred-million-user architecture prematurely) wastes scarce engineering time on generality nobody needs yet; the discipline is building just enough structure to avoid the "no documentation, no versioning, no reuse" failure mode, not replicating every feature of a large platform's design.
Implement a rolling-window Kolmogorov-Smirnov test in Python to detect distribution drift for a streaming numeric feature: it should accept a reference sample, a stream of new values, a window size, and an alpha threshold, and yield the indexes where the KS p-value drops below alpha. Describe the performance considerations for running this on streaming data.
Sample Answer
Direct answer. Slide a fixed-size window across the incoming stream, run a two-sample Kolmogorov-Smirnov test between the reference sample and each window, and flag the window's end index whenever the KS p-value drops below the alpha threshold.
Code (executed and verified: near-zero alerts on a stable stream, a clear cluster of alerts once real drift is injected).
from scipy.stats import ks_2samp
import numpy as np
def rolling_ks_drift(reference, stream, window, alpha=0.05):
reference, stream = np.asarray(reference), np.asarray(stream)
alerts = []
for end in range(window, len(stream) + 1):
window_vals = stream[end - window:end]
_, p = ks_2samp(reference, window_vals)
if p < alpha:
alerts.append(end - 1)
return alerts
Worked example (recomputed: 500-point reference, 300-point stream with drift injected halfway through). On a stream with NO real drift, the detector raised 0 alerts at alpha=0.01 over 250 window positions. On a stream where the mean genuinely shifts by 1.2 standard deviations starting at position 150, the detector raised 126 alerts, with the first one appearing once the sliding window (size 50) was substantially populated with post-drift points, consistent with the drift's true onset.
Structured elaboration: performance considerations for streaming. Recomputing a full two-sample KS test from scratch on every new point is the naive version above (each call re-sorts the window, an O(window log window) cost per step); at high throughput, the standard mitigation is to only re-run the test every N new points (a "check cadence") rather than after every single one, and to maintain the window as a sorted structure incrementally (a running sorted deque or a small order-statistics tree) rather than re-sorting it from scratch each time. Keeping the reference sample fixed and reasonably sized (not re-growing it as more data arrives) bounds the reference side's contribution to the test's cost, since KS test cost scales with both sample sizes.
Trade-offs and pitfalls. A window that's too small gives a noisy, low-power test that both misses real drift and false-alarms on ordinary sampling variation; a window that's too large delays detection because it takes a while for enough post-drift points to outweigh the pre-drift ones already in the window, exactly what the "first alert" delay in the worked example shows. Multiple testing matters here too: running a fresh hypothesis test at every sliding step, or across many features simultaneously, inflates the overall false-positive rate unless you either widen alpha's effective bar (Bonferroni-style) or require several consecutive flagged windows before actually alerting a human.
Describe the difference between structured and unstructured pruning techniques for neural networks. For each approach, explain how pruning is applied, what sparsity patterns result, the implications for actual runtime speedups on CPU/GPU, and situations where you would prefer one over the other in production.
Sample Answer
Definition and core difference:
- Structured pruning removes whole higher-level units (channels, filters, attention heads, or entire neurons/columns/rows). Unstructured pruning removes individual weights (connections) anywhere in the weight tensors.
How pruning is applied:
- Structured: measure importance per structure (L1-norm of channel, magnitude of filter outputs, or learned gating), then zero-out and remove those units; often followed by fine-tuning.
- Unstructured: rank weights by magnitude or use regularizers (L0/L1, movement pruning) and set many individual weights to zero; may prune during or after training and fine-tune.
Sparsity patterns:
- Structured → coarse-grained sparsity (dense smaller layers, e.g., N_out reduced channels). Resulting model shape changes.
- Unstructured → fine-grained, irregular sparsity mask across tensors.
Implications for runtime speedups:
- Structured pruning yields straightforward speedups on CPU/GPU because reduced dimensions map to smaller dense matrix multiplies and less memory - immediate latency and throughput gains and simpler deployment.
- Unstructured pruning can reduce FLOPs (floating-point operations) but often gives limited real-world speedup on standard GPUs/CPUs because irregular sparse kernels have overheads (indexing, memory fragmentation). Gains are achievable on CPU with optimized sparse libraries or on accelerators (TPU/GPUs) that support sparse primitives or with high sparsity levels and specialized runtimes.
When to prefer each in production:
- Prefer structured when you need predictable, portable latency/throughput improvements, simpler deployment, or must fit model into fixed inference hardware (edge devices, mobile). Good trade-off for moderate accuracy loss.
- Prefer unstructured when maximizing parameter/FLOP reduction for research, model compression, or when you have access to runtimes that exploit fine-grained sparsity (sparse inference engines, certain datacenter accelerators), or when preserving model accuracy is critical and structured pruning hurts performance more.
Practical note: a hybrid approach (block or pattern sparsity, or structured pruning followed by fine unstructured pruning) often balances accuracy and deployability. Always validate speedups on target hardware and include fine-tuning after pruning.
Also covers (folded from merged near-duplicates): 36ba1085 folds pruning-vs-quantization combined pitfalls; 3ab3f96c folds hardware/sparsity-runtime mapping.
Given a set of items, each with a weight and a value, and a capacity budget, choose a subset that maximizes total value without exceeding the budget, where each item can be taken at most once. Explain the DP state you use and how it changes if you only need to know whether some exact target sum is achievable at all, rather than the maximum value.
Sample Answer
Direct answer
The 0/1 knapsack DP state is dp[c] meaning "maximum total value achievable using a budget of exactly (or up to) c," updated per item by dp[c] = max(dp[c], dp[c - weight] + value), iterating capacities in descending order so each item is only used once. If the question changes from "maximize value" to "is some exact target sum achievable at all," the state becomes a boolean reachable[s] instead of a running maximum, using the identical recurrence shape (reachable[s] = reachable[s] or reachable[s - weight]) but tracking reachability instead of an optimum. This exact-sum variant is the same shape as the well-known Partition Equal Subset Sum problem, which asks whether a set of numbers can be split into two subsets with equal totals.
Structured elaboration
Value-maximization DP.
def knapsack_max_value(weights, values, capacity):
"""
0/1 knapsack: maximum total value without exceeding capacity, each item
at most once. dp[c] = best value achievable with budget c.
Time O(n * capacity), Space O(capacity) (rolling 1D array).
"""
dp = [0] * (capacity + 1)
for w, v in zip(weights, values):
for c in range(capacity, w - 1, -1): # descending: each item used at most once
dp[c] = max(dp[c], dp[c - w] + v)
return dp[capacity]
Feasibility (exact-sum) DP. Change the table's meaning from "best value so far" to "is this sum reachable," and change the update from a max to a boolean OR:
def subset_sum_feasible(weights, target):
"""
Can some subset of weights sum to exactly target?
reachable[s] = True if sum s is achievable using a subset of items seen
so far. Same 0/1 recurrence as knapsack, but the DP value is a boolean
"reachable" flag instead of a running maximum.
Time O(n * target), Space O(target).
"""
reachable = [False] * (target + 1)
reachable[0] = True
for w in weights:
for s in range(target, w - 1, -1):
if reachable[s - w]:
reachable[s] = True
return reachable[target]
Partition Equal Subset Sum is exactly this feasibility check with target set to half the total sum of the input numbers (if the total is odd, an equal split is impossible immediately, no DP needed). The same feasibility shape also applies to budget-constrained subset-selection outside pure combinatorics: for example, choosing dashboard KPIs or metrics under a display-cost budget, where each metric has a fixed "screen cost" and you want to know whether some subset exactly fills an allotted display budget (or, with the max-value version, which subset of metrics maximizes total business value within that budget).
Worked example
weights = [2, 3, 4, 5]
values = [3, 4, 5, 6]
print(knapsack_max_value(weights, values, 5))
Output: 7 (taking the weight-2/value-3 and weight-3/value-4 items exactly fills the capacity-5 budget for total value 7; no other combination of these items reaches higher value within capacity 5).
nums = [1, 5, 11, 5]
total = sum(nums)
print(total, total % 2 == 0, subset_sum_feasible(nums, total // 2) if total % 2 == 0 else None)
Output: 22 True True. The total is 22 (even), so an equal split needs a subset summing to 11; subset_sum_feasible confirms 11 is reachable (via 5 + 5 + 1), so [1, 5, 11, 5] can be partitioned into two equal-sum halves.
Trade-offs & pitfalls
Key points
- Greedy selection by value-to-weight ratio is optimal for the fractional knapsack (where you can take a fraction of an item) but is not guaranteed optimal for 0/1 knapsack, since taking a high-ratio item can leave awkward leftover capacity that a different combination would have used better.
- The feasibility DP is strictly cheaper to reason about than the value-maximization DP (booleans instead of running maxima), but it answers a narrower question: it tells you whether a target is reachable, not which subset achieves it, unless you also track parent pointers or reconstruct the choice by scanning backward through the table.
- Both DP variants are pseudo-polynomial: their cost scales with the numeric capacity or target value, not just the number of items, so a very large capacity or target (in the millions) can make the DP impractical even though the item count is small; that is where a greedy approximation or a meet-in-the-middle exact method becomes attractive.
Complexity
- Value-maximization: time O(n⋅W), space O(W), where n is the item count and W is the capacity.
- Feasibility: time O(n⋅T), space O(T), where T is the target sum.
Edge cases
- Target or capacity of 0:
dp[0]/reachable[0]are the trivial base cases (empty selection), both handled directly. - An item heavier than the remaining capacity: naturally excluded by the descending-range guard (
w - 1lower bound), never considered for smaller capacities. - Odd total sum in the partition-equal-subset-sum framing: no DP needed at all, an equal-value split is impossible by simple arithmetic before touching the table.
Write a Python function that, given numpy arrays y_true, y_pred, and a binary sensitive_attr, computes (1) the demographic parity difference (the difference in positive-prediction rates between groups) and (2) the equalized-odds differences (absolute differences in false positive rate and true positive rate between groups). Handle missing sensitive-attribute values by excluding those rows.
Sample Answer
Direct answer: below is a vectorized function computing demographic parity difference and both components of the equalized-odds gap (TPR and FPR differences) from raw prediction arrays, handling missing sensitive-attribute values by excluding those rows inside the function itself.
Structured elaboration. Demographic parity difference asks whether the positive-PREDICTION rate differs by group, regardless of the true label. The equalized-odds gaps ask, separately among truly-positive and truly-negative individuals, whether the prediction rate differs by group. These answer different questions and can disagree, which is exactly the point of computing both.
Worked example (executed).
import numpy as np
def demographic_parity_and_equalized_odds(y_true, y_pred, sensitive_attr):
y_true = np.asarray(y_true, dtype=float)
y_pred = np.asarray(y_pred, dtype=float)
sensitive_attr = np.asarray(sensitive_attr, dtype=float)
valid = ~np.isnan(sensitive_attr) # exclude rows with a missing sensitive attribute
n_dropped = int((~valid).sum())
y_true, y_pred, sensitive_attr = y_true[valid], y_pred[valid], sensitive_attr[valid]
groups = np.unique(sensitive_attr)
if len(groups) != 2:
raise ValueError("expects exactly two groups after dropping missing sensitive_attr rows")
g0, g1 = groups
def group_rate(mask_g):
if mask_g.sum() == 0:
return np.nan, np.nan, np.nan
pos_rate = y_pred[mask_g].mean()
pos, neg = y_true[mask_g] == 1, y_true[mask_g] == 0
tpr = y_pred[mask_g][pos].mean() if pos.sum() > 0 else np.nan
fpr = y_pred[mask_g][neg].mean() if neg.sum() > 0 else np.nan
return pos_rate, tpr, fpr
pr0, tpr0, fpr0 = group_rate(sensitive_attr == g0)
pr1, tpr1, fpr1 = group_rate(sensitive_attr == g1)
return {"demographic_parity_difference": abs(pr0 - pr1),
"tpr_gap": abs(tpr0 - tpr1), "fpr_gap": abs(fpr0 - fpr1),
"group_positive_rates": {str(g0): pr0, str(g1): pr1},
"n_dropped_missing_sensitive": n_dropped}
y_true = [1,0,1,0,1,1,0,0,1,0]
y_pred = [1,1,1,0,0,1,0,1,1,0]
sens = [0,0,0,0,0,1,1,1,1,1]
print(demographic_parity_and_equalized_odds(y_true, y_pred, sens))
# Same data with one extra row whose sensitive attribute is missing (NaN)
y_true2, y_pred2, sens2 = y_true + [1], y_pred + [1], sens + [float("nan")]
print(demographic_parity_and_equalized_odds(y_true2, y_pred2, sens2))
Output:
{'demographic_parity_difference': 0.0, 'tpr_gap': 0.333, 'fpr_gap': 0.167, 'group_positive_rates': {'0.0': 0.6, '1.0': 0.6}, 'n_dropped_missing_sensitive': 0}
{'demographic_parity_difference': 0.0, 'tpr_gap': 0.333, 'fpr_gap': 0.167, 'group_positive_rates': {'0.0': 0.6, '1.0': 0.6}, 'n_dropped_missing_sensitive': 1}
This is a deliberately instructive example: the two groups have IDENTICAL overall positive-prediction rates (0.6 each), so demographic parity difference is exactly zero, but the true-positive rate differs by 33 percentage points between groups. A dashboard that reports only demographic parity would call this model fair; it is not, once you look at who is actually being served correctly within each group. The second call shows the missing-value handling working as required: adding one more row with a NaN sensitive attribute leaves every reported rate unchanged and simply reports n_dropped_missing_sensitive: 1, rather than raising an error or silently treating the missing value as its own group.
Trade-offs and pitfalls. (1) Rows with a missing (NaN) sensitive attribute are dropped by the function itself (via the np.isnan mask) rather than left for the caller to filter, or treated as a third group, which would otherwise make the group-count check raise on data that is actually just two groups plus some missing labels; the function reports how many rows it dropped so a caller can log or alert on an unexpectedly high drop count. (2) With small per-group counts the rates are noisy; do not report a gap without also reporting the group sizes. (3) Do not stop at demographic parity difference alone, as this exact worked example shows.
Want to create your own tailored preparation guide using our deep research?
Get Started for FreeInterview-Ready Courses
Visual-first, interactive, structured learning paths
Browse Applied Scientist jobs
AI-enriched listings across hundreds of company career pages
Explore Jobs