← DoorDash Interview Insights

DoorDash·Software Engineer·Onsite - System Design / Architecture·Senior

SeniorPrefer not to say
Jun 2026

Summary

DoorDash system design round for a software engineering role, centered entirely on building a real-time driver pay computation system from scratch. It started as a coding problem and kept expanding into distributed systems territory, which I wasn't fully prepared for.

Questions Asked (10)

Q1

Given a driver's work intervals for a day and a set of peak-hour windows with pay multipliers, compute the driver's total daily pay. Work intervals can cross peak boundaries, so you need to split and pay each sub-interval at the correct rate.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This looked like a clean interval math problem and I dove straight into slicing each interval at every peak boundary.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem: confirm that work intervals and peak windows are given as lists of [start, end] times, pay rates are base rate plus multipliers for peak windows, and intervals are half-open [start, end). Then outline a sweep-line algorithm: create events for all interval and peak boundaries, sort them, and sweep through time, maintaining the current pay rate and accumulating pay for each segment. Finally, discuss edge cases and complexity.

Pro tip: Mention that you would use a sweep-line approach because it elegantly handles overlapping intervals and boundaries, and that you would clarify whether peak windows can overlap or be adjacent, as that affects rate determination.

1. Clarify requirements and assumptions

Ask about input format, time granularity, whether intervals are inclusive/exclusive, if peak windows can overlap, and how pay is calculated (e.g., base rate * multiplier). Confirm that work intervals are non-overlapping and sorted, or if not, how to handle overlaps.

2. Design the algorithm

Propose a sweep-line approach: create events for all start and end times of work intervals and peak windows, sort them, and sweep through time. Maintain a counter of active work intervals and active peak windows to determine the current pay rate for each segment.

3. Handle rate determination and pay calculation

For each segment between consecutive events, if there is at least one active work interval, compute the pay rate: base rate multiplied by the product of multipliers for all active peak windows (or the maximum multiplier if they don't stack). Accumulate pay by multiplying the segment duration by the rate.

4. Analyze complexity and edge cases

State that sorting takes O(n log n) where n is the total number of events, and the sweep is O(n). Discuss edge cases: intervals crossing peak boundaries, zero-length intervals, peak windows outside work hours, and overlapping peak windows.

5. Test with examples

Walk through a simple example, such as a work interval from 10:00 to 14:00 with a peak window from 11:00 to 13:00 and multiplier 1.5, to verify the algorithm splits correctly and computes pay accurately.

Key Points to Mention

  • Sweep-line algorithm for efficient interval processing
  • Time complexity: O(n log n) due to sorting, O(n) for sweep
  • Handling of half-open intervals [start, end) to avoid double-counting boundaries
  • Determining pay rate when multiple peak windows overlap (stacking vs. max)
  • Edge cases: intervals crossing peak boundaries, zero-length intervals, peak windows outside work hours
  • Clarifying questions about input format and pay calculation rules

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

How would you design the end-to-end streaming pipeline that continuously computes each driver's daily pay from a high-volume stream of order events?

System DesignTechnical Trade-offs
Author's notes

I went straight to Kafka and a single consumer group, which the interviewer let me run with for a bit before asking how I'd partition.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and scale, then propose a high-level architecture using a streaming platform like Kafka and a stream processor like Flink. Focus on how to compute daily pay accurately and efficiently, discussing windowing, state management, and exactly-once semantics.

Pro tip: Emphasize the trade-offs between latency and accuracy, and how you would handle late or out-of-order events to ensure correct pay calculations. Mention the importance of idempotency and reconciliation with batch processing for financial accuracy.

1. Clarify Requirements and Scale

Ask about event volume, latency requirements, and whether pay computation must be exact or approximate. Understand the definition of daily pay and any business rules.

2. Design High-Level Architecture

Propose a pipeline: ingest order events via Kafka, process with a stream processor (e.g., Flink), store state in a scalable store (e.g., RocksDB), and output to a database or downstream system.

3. Detail Stream Processing Logic

Explain how to group events by driver and day, apply windowing (e.g., tumbling windows with allowed lateness), and compute pay using aggregations. Discuss handling of late events and watermarks.

4. Ensure Fault Tolerance and Exactly-Once Semantics

Describe checkpointing, state recovery, and idempotent writes to avoid double-counting. Mention the need for transactional sinks or deduplication.

5. Address Scalability and Monitoring

Discuss partitioning by driver ID for parallelism, scaling the stream processor, and monitoring for lag, errors, and correctness. Include reconciliation with batch jobs for financial accuracy.

Key Points to Mention

  • Use of Kafka for durable, scalable event ingestion with partitioning by driver ID.
  • Stream processing with Flink or Spark Streaming, leveraging event-time processing and watermarks.
  • Windowing strategies: tumbling windows for daily aggregation, with allowed lateness to handle out-of-order events.
  • State management: keyed state per driver, checkpointing for fault tolerance, and exactly-once processing guarantees.
  • Idempotent output and reconciliation: writing to a database with upserts, and periodic batch jobs to correct any discrepancies.
  • Scalability considerations: horizontal scaling of stream processors, backpressure handling, and monitoring for performance and correctness.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

The system receives events with at-least-once delivery guarantees, meaning duplicates, out-of-order arrivals, and late events are all possible. How do you keep daily pay totals correct under these conditions?

System DesignData Modeling
Author's notes

Idempotency was the first thing I said and I think I said it right, tying dedup to a stable event id before any aggregate changes.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by acknowledging the challenges of at-least-once delivery and the need for idempotency and correct ordering. Propose a design that uses unique event identifiers for deduplication, event-time processing with watermarks to handle out-of-order and late events, and a scalable storage solution that supports upserts. Emphasize how these mechanisms ensure accurate daily pay totals despite duplicates, out-of-order arrivals, and late events.

Pro tip: Mention that you would monitor the lag and completeness of the daily totals, and have a reconciliation process to handle any late events that arrive after the daily cutoff, ensuring financial accuracy.

1. Clarify requirements and constraints

Confirm the definition of 'daily pay totals' (e.g., per Dasher, per day, in which timezone) and the acceptable latency for correctness. Discuss the impact of duplicates, out-of-order, and late events on the business.

2. Design for idempotency and deduplication

Use unique event IDs (e.g., delivery ID + event type) to deduplicate events. Store processed event IDs in a durable store with TTL or use a database unique constraint to ignore duplicates.

3. Handle out-of-order and late events

Process events based on event time, not arrival time. Use watermarks to track progress and allow a grace period for late events. For events arriving after the grace period, update the daily total via a correction mechanism.

4. Choose a scalable and consistent storage solution

Use a database that supports atomic upserts (e.g., PostgreSQL with ON CONFLICT, Cassandra, or DynamoDB) to maintain running totals per Dasher per day. Ensure the storage can handle high write throughput and provide read-after-write consistency for the totals.

5. Implement monitoring and reconciliation

Monitor for duplicates, late events, and discrepancies. Periodically reconcile totals with source data to catch any missed events. Consider a batch job that recomputes daily totals from raw events for auditing.

Key Points to Mention

  • Idempotency: using unique event IDs to deduplicate
  • Event-time processing with watermarks to handle out-of-order and late events
  • Grace period and late event handling: updating totals after the fact
  • Storage: atomic upserts and scalable databases for running totals
  • Monitoring and reconciliation to ensure accuracy
  • Trade-offs between latency and completeness

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

A day's worth of raw events across all drivers won't fit in memory on one machine. How do you keep streaming state bounded, and how do you recompute historical totals when you need to backfill or reconcile?

System DesignTechnical Trade-offs
Author's notes

Talked about keeping only active keyed state in memory and archiving raw events to object storage.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by framing the problem as a streaming aggregation challenge: use windowed, keyed state with incremental aggregation and TTL-based eviction to keep memory bounded. Then explain how to store immutable raw events in durable storage (e.g., Kafka + S3) and use a batch or stream reprocessing pipeline to recompute historical totals for backfill or reconciliation, ensuring idempotency and exactly-once semantics.

Pro tip: Emphasize that bounded state is achieved by aggregating early and often, not by storing raw events; and for backfill, use a separate pipeline that reads from the immutable log and writes to a new table, then swap atomically to avoid downtime.

1. Clarify requirements and constraints

Ask about the expected event volume, latency requirements, and whether exact or approximate totals are acceptable. Confirm that raw events are durably stored and can be replayed.

2. Design bounded streaming state

Use keyed state (e.g., per driver) with time windows and incremental aggregation (sum, count). Apply TTL or explicit eviction to drop old state, and use RocksDB or similar for disk-backed state if needed.

3. Ensure durability and replayability

Persist raw events to a durable, immutable log (e.g., Kafka) and long-term storage (e.g., S3). This enables reprocessing without relying on in-memory state.

4. Implement backfill and reconciliation

Run a batch job or a separate streaming job that reads from the raw event store, recomputes aggregates, and writes to a new version of the output table. Use idempotent writes and exactly-once semantics.

5. Handle consistency and cutover

Atomically swap the new table with the old one, or use a dual-write approach with validation. Monitor for discrepancies and have a rollback plan.

Key Points to Mention

  • Windowed aggregations (tumbling, sliding, session) with incremental updates
  • State TTL and eviction policies to bound memory
  • Durable event log (Kafka) and long-term storage (S3) for replay
  • Idempotent processing and exactly-once semantics (e.g., Flink checkpoints, Kafka transactions)
  • Backfill via batch reprocessing or separate streaming job
  • Atomic table swap or dual-write for reconciliation without downtime

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

If a consumer crashes mid-day, how do you recover without losing any pay or double-counting it?

System DesignTechnical Trade-offs
Author's notes

The key is offset commit ordering relative to durable state writes, and I got that right.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the scenario: a consumer service crashes mid-day, and we must recover without losing pay (i.e., ensure all completed deliveries are paid) or double-counting (i.e., avoid paying twice for the same delivery). Then propose a design that uses idempotent processing, durable event logging, and reconciliation to guarantee exactly-once semantics for payouts.

Pro tip: Emphasize that exactly-once is achieved through at-least-once delivery plus idempotent consumers, and mention that you would use a unique idempotency key per delivery to deduplicate payments.

1. Clarify requirements and scope

Confirm what 'consumer' means (e.g., a service that processes delivery events) and what 'pay' refers to (e.g., Dasher payouts). Establish that the goal is to recover without financial discrepancies.

2. Design for idempotency and durability

Propose that all payment-related events be persisted in a durable log (e.g., Kafka) and that the consumer processes them idempotently using a unique key (e.g., delivery ID) to prevent double-counting.

3. Implement recovery and reconciliation

Describe how the consumer can resume from its last committed offset after a crash, and how a reconciliation job can compare the event log with the payment database to detect and correct any missing or duplicate payments.

4. Handle failures and edge cases

Discuss strategies for partial failures, such as transactional writes, two-phase commit, or compensating transactions, and how to handle late-arriving events or out-of-order processing.

5. Monitor and validate

Mention the importance of monitoring for discrepancies, alerting on anomalies, and running regular audits to ensure the system remains correct over time.

Key Points to Mention

  • Idempotency keys (e.g., delivery ID) to deduplicate payments
  • Durable event log (e.g., Kafka) with at-least-once delivery
  • Consumer offset management and replay from last committed offset
  • Reconciliation between event log and payment database
  • Transactional guarantees or exactly-once processing patterns
  • Monitoring and alerting for payment discrepancies

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

If your processing pipeline needs to call an upstream service per event, how do you protect both your system and theirs under high load?

API & IntegrationsSystem Design
Author's notes

Standard stuff: retries with backoff and jitter, circuit breakers, rate limiting, backpressure.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by acknowledging the dual goal: protect your pipeline from cascading failures and protect the upstream service from being overwhelmed. Then walk through a layered defense strategy covering backpressure, rate limiting, circuit breaking, and graceful degradation, and tie it to DoorDash's high-throughput, latency-sensitive environment.

Pro tip: Emphasize that you'd negotiate rate limits and SLAs with the upstream team upfront, and design for graceful degradation (e.g., queueing, fallbacks) rather than just throwing retries at the problem.

1. Clarify requirements and constraints

Ask about event volume, latency SLAs, upstream capacity, and whether the upstream is internal or third-party. This shows you don't jump to solutions without understanding the problem.

2. Apply backpressure and rate limiting

Use bounded queues, concurrency limits, and client-side rate limiting to prevent overwhelming the upstream. Mention token bucket or leaky bucket algorithms.

3. Implement circuit breaking and retries with jitter

Add circuit breakers to fail fast when the upstream is unhealthy, and use exponential backoff with jitter for retries to avoid thundering herd.

4. Design for graceful degradation

Define fallback behavior: queue events for later, use cached responses, or drop non-critical events. Ensure your pipeline remains responsive.

5. Monitor, alert, and iterate

Instrument metrics (latency, error rates, queue depth) and set up alerts. Use load testing to validate limits and adjust dynamically.

Key Points to Mention

  • Backpressure mechanisms like bounded queues and concurrency limits
  • Rate limiting algorithms (token bucket, leaky bucket) and client-side throttling
  • Circuit breaker pattern to prevent cascading failures
  • Retry strategies with exponential backoff and jitter
  • Graceful degradation and fallback options (queueing, caching, dropping)
  • Observability: metrics, logging, and alerting for both systems
  • Negotiating SLAs and rate limits with upstream service owners

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q7

Peak window configurations for today are updated at 5pm, changing a multiplier for a window that already passed. How do you fix the already-accumulated pay for affected drivers, and what does the driver-facing number show in the meantime?

System DesignRoot Cause Analysis
Author's notes

This one was rough.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the requirements: whether the correction should be automatic or manual, and what the driver-facing number should show. Then, propose a solution that includes a reconciliation job to adjust past pay and a real-time display that reflects the latest multiplier, with clear communication to drivers.

Pro tip: Emphasize the importance of idempotency and auditability in the reconciliation process to avoid double payments and ensure traceability. Also, consider the driver experience: transparency about adjustments builds trust.

1. Clarify Requirements and Constraints

Ask questions to understand if the correction should be automatic, the acceptable delay, and any compliance or driver communication policies. Determine if the multiplier change is a one-time event or recurring.

2. Design Reconciliation Process

Propose a batch job that identifies affected deliveries, recalculates pay with the updated multiplier, and issues adjustments (credits or debits) to driver accounts. Ensure idempotency to prevent duplicate adjustments.

3. Handle Driver-Facing Display

Decide what the driver sees in the meantime: either show the original amount with a pending adjustment note, or immediately update to the new amount. Consider real-time updates and clear labeling.

4. Implement Safeguards and Monitoring

Add logging, alerting, and audit trails for the reconciliation. Include a rollback plan in case of errors. Monitor for anomalies like negative balances or excessive adjustments.

5. Communicate and Iterate

Notify drivers about the adjustment through in-app messages or email. Gather feedback and iterate on the process to improve accuracy and timeliness.

Key Points to Mention

  • Idempotency in reconciliation to avoid double payments
  • Audit trail and logging for compliance and debugging
  • Driver communication and transparency about adjustments
  • Real-time vs. batch processing trade-offs
  • Edge cases: drivers who cashed out, negative balances, and tax implications
  • Data consistency and transaction isolation in distributed systems

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q8

A bug shipped this morning that over-counted peak pay for some drivers. Walk through how you'd detect it, recompute correct totals from the raw event log, and reconcile without anyone getting paid twice.

Root Cause AnalysisSystem Design
Author's notes

Detection first: reconciliation deltas between streaming output and a recomputed batch job would surface this.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by describing how you would detect the bug through monitoring and anomaly detection, then explain a systematic process to recompute correct totals from the raw event log using idempotent operations, and finally outline a reconciliation strategy that ensures no double payments by comparing and adjusting only the differences.

Pro tip: Emphasize the importance of idempotency and auditability in your solution—use unique transaction IDs and maintain a clear audit trail to prevent duplicate payments and facilitate rollback if needed.

1. Detect the Bug

Use monitoring alerts, anomaly detection, and driver reports to identify the over-counting issue. Compare expected vs. actual peak pay totals to quantify the impact.

2. Recompute Correct Totals

Process the raw event log to recalculate peak pay for affected drivers, ensuring idempotency by using unique event IDs and deduplication logic.

3. Reconcile Payments

Compare recomputed totals with already-paid amounts. For overpayments, decide whether to adjust future payments or issue corrections; for underpayments, initiate additional payments.

4. Prevent Double Payment

Implement idempotent payment operations and maintain a ledger of adjustments. Use transaction IDs and status checks to avoid duplicate disbursements.

5. Communicate and Monitor

Inform stakeholders (finance, support, drivers) about the issue and resolution. Add monitoring to detect similar bugs and validate the fix.

Key Points to Mention

  • Idempotency in recomputation and payment processing
  • Use of raw event log as source of truth
  • Anomaly detection and monitoring for bug detection
  • Reconciliation strategies: netting, adjustments, or separate corrections
  • Audit trail and logging for compliance and debugging
  • Communication with affected drivers and stakeholders

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q9

The driver app needs to show each driver their pay so far today with sub-second latency, at scale across millions of drivers. How does the read path differ from the write path?

System DesignTechnical Trade-offs
Author's notes

Decouple the serving layer from the streaming state entirely.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: read path must serve millions of drivers with sub-second latency, while write path ingests frequent pay updates. Then contrast the two paths: write path prioritizes durability and throughput, read path prioritizes low-latency, high-throughput reads, likely using caching, denormalization, and read replicas. Finally, discuss trade-offs like consistency vs. latency and propose a specific architecture.

Pro tip: Emphasize that the read path is optimized for speed and scale, often serving precomputed or cached data, while the write path ensures data integrity and handles high write volume. Mention that eventual consistency is acceptable for pay display as long as it's bounded and transparent to drivers.

1. Clarify Requirements and Scale

Confirm the read QPS (e.g., millions of drivers checking frequently), write QPS (e.g., updates per delivery), latency SLA (sub-second), and consistency needs (e.g., can pay be slightly stale?).

2. Design the Write Path

Focus on durability, throughput, and correctness: use a transactional database or event stream (e.g., Kafka) to ingest pay updates, with partitioning by driver ID for scalability.

3. Design the Read Path

Optimize for low latency and high throughput: use a cache (e.g., Redis) with precomputed daily pay totals, read replicas, and possibly a CDN or edge caching for global drivers.

4. Address Consistency and Freshness

Decide on consistency model: e.g., eventual consistency with a short TTL (e.g., 1-5 seconds) or write-through caching to keep reads fresh while meeting latency.

5. Discuss Trade-offs and Failure Modes

Compare options: strong consistency vs. latency, cache invalidation strategies, and how to handle cache misses or stale data without violating SLA.

Key Points to Mention

  • Read path uses caching (e.g., Redis) and denormalized views to achieve sub-second latency, while write path uses a durable, transactional store.
  • Write path may use event sourcing or change data capture (CDC) to propagate updates to read-optimized stores asynchronously.
  • Partitioning by driver ID ensures scalability for both reads and writes, but read path may need global replication for low latency across regions.
  • Consistency trade-off: eventual consistency is acceptable for pay display if bounded (e.g., a few seconds) and if drivers are informed.
  • Read path can precompute daily totals incrementally to avoid expensive aggregations at read time.
  • Consider using a multi-tier cache (in-memory, distributed cache) and read replicas to handle read-heavy load.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q10

One driver or order key is generating way more events than others, causing one consumer partition to lag badly. How do you detect and fix the skew without breaking per-key ordering?

System DesignTechnical Trade-offs
Author's notes

Consumer lag metrics per partition is how you detect it.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining how you would detect the skew using consumer lag metrics and per-key event rate monitoring. Then propose a solution that preserves per-key ordering, such as splitting the hot key into sub-keys with a deterministic mapping or using a two-stage aggregation with a local buffer and a global ordering service. Emphasize trade-offs and validation.

Pro tip: Mention that you would first try to reduce the hot key's load by optimizing the producer or consumer logic before resorting to architectural changes. Also, highlight the importance of monitoring and alerting to catch skew early.

1. Detect the skew

Use consumer lag metrics per partition and per-key event rate monitoring to identify the hot key. Look for a single partition with significantly higher lag and a key producing orders of magnitude more events.

2. Analyze root cause

Determine why the key is hot: is it a legitimate spike, a bug, or a design issue? Check if the key represents a high-volume entity like a popular restaurant or a bot.

3. Choose a strategy to mitigate

Options: (a) split the hot key into sub-keys (e.g., key + shard ID) and process in parallel, then merge results while preserving order per sub-key; (b) use a two-stage approach: first stage partitions by key, second stage reorders; (c) offload the hot key to a dedicated consumer group with a single consumer to maintain order.

4. Implement with ordering guarantees

If splitting, ensure that all events for a given original key go to the same sub-key consistently (e.g., using a hash of the event ID modulo N). For two-stage, use a local buffer and a global sequencer. Document the ordering semantics.

5. Validate and monitor

After deployment, verify that lag is reduced and ordering is preserved via integration tests. Set up alerts for future skew and consider auto-scaling or dynamic partitioning.

Key Points to Mention

  • Consumer lag monitoring per partition and per key
  • Hot key detection techniques (e.g., sampling, counting)
  • Preserving per-key ordering: consistent hashing, sub-key partitioning
  • Two-stage processing with local buffering and global ordering
  • Trade-offs: increased complexity, potential latency, resource usage
  • Testing and validation of ordering guarantees

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.