← DoorDash Interview Insights

DoorDash·Software Engineer·Technical Phone Screen·Senior

Senior
Jul 2026

Summary

DoorDash software engineering interview centered on a workflow engine problem for order processing. The coding portion was pretty involved and the follow-ups pushed into design territory fast.

Questions Asked (6)

Q1

You're given a skeleton workflow engine for order processing where nodes receive an order context and return the next node id. Implement the missing node logic for refunding orders that have timed out, including a timeout decision node, a refund node, and an end node.

System DesignAPI & IntegrationsData Modeling
Author's notes

This was a lot more state-management than I expected from what looked like a graph traversal problem.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the workflow engine's contract: how nodes are invoked, what the order context contains, and how the next node is determined. Then design the timeout decision node to check the order's age against a threshold, the refund node to call the payment service idempotently, and the end node to finalize the order state. Ensure the logic is testable and handles edge cases like already-refunded orders.

Pro tip: Emphasize idempotency in the refund node—use a unique idempotency key derived from the order ID to prevent duplicate refunds if the node is retried. This shows you understand real-world payment systems and failure modes.

1. Clarify the workflow engine contract

Ask how nodes are executed, what the order context includes (e.g., timestamps, status, payment details), and how the next node is selected. Confirm error handling and retry semantics.

2. Design the timeout decision node

Implement logic to compare the order's creation or last-updated time against a timeout threshold. Return the refund node if timed out, otherwise the end node.

3. Implement the refund node

Call the payment service to issue a refund, ensuring idempotency with a unique key. Update the order context to mark it as refunded and handle failures gracefully.

4. Implement the end node

Finalize the order by updating its status (e.g., 'refunded' or 'completed') and persisting any necessary data. Return a terminal signal or null to end the workflow.

5. Test and validate

Write unit tests for each node covering timeout, non-timeout, refund success, refund failure, and idempotency scenarios. Consider integration tests with a mock payment service.

Key Points to Mention

  • Idempotency of refund operations to avoid double refunds on retries
  • Clear separation of concerns: decision logic, side effects, and termination
  • Error handling and retry strategies for payment service calls
  • Use of order context to store state and pass data between nodes
  • Timeout threshold configuration and clock skew considerations
  • Testing strategy including edge cases and failure modes

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

Q2

How do you ensure the refund workflow is safe to retry and that the same order is never refunded twice?

Technical Trade-offsAPI & Integrations
Author's notes

Talked through idempotency keys derived from the order id.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining idempotency and its importance in payment systems, then explain how you would design the refund workflow with idempotency keys and transactional guarantees. Walk through the end-to-end flow, highlighting how you prevent duplicate refunds even with retries, network failures, or concurrent requests.

Pro tip: Emphasize that idempotency must be enforced at the data layer with a unique constraint on the idempotency key, not just in application logic, to handle race conditions and distributed retries. Also mention the importance of logging and monitoring to detect and alert on duplicate refund attempts.

1. Define Idempotency and Requirements

Explain that idempotency means multiple identical requests have the same effect as one, and that the refund workflow must be safe to retry without double-refunding. Clarify that this is critical for financial integrity and customer trust.

2. Design with Idempotency Keys

Describe how each refund request includes a unique idempotency key generated by the client or server. The key is stored in a database with a unique constraint, so duplicate requests with the same key are rejected or return the original result.

3. Implement Transactional Guarantees

Use database transactions to atomically check and insert the idempotency key, and update the order status to 'refunded'. This ensures that even if two requests arrive simultaneously, only one succeeds.

4. Handle Retries and Failures Gracefully

Explain that on retry, the system should first check if the idempotency key exists and return the stored response. If the original request failed mid-way, the transaction rollback ensures no partial state, and the retry can safely proceed.

5. Monitor and Audit

Mention logging all refund attempts with idempotency keys and setting up alerts for duplicate key violations or unusual patterns. Regular audits can verify that no order was refunded twice.

Key Points to Mention

  • Idempotency keys with unique database constraints
  • Database transactions and atomic operations
  • Handling concurrent requests and race conditions
  • Storing and returning the original response for duplicate requests
  • Logging, monitoring, and alerting for duplicate refund attempts
  • End-to-end testing including failure injection and retries

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

Q3

Write unit tests covering the not-timed-out path, the timed-out refund path, the completed order path, a retry scenario, and a duplicate execution scenario.

Technical Trade-offsAlgorithms & Data Structures
Author's notes

The duplicate execution test was the one I found most interesting to think through.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the system under test—likely a payment or order processing service with timeout and refund logic—and identify the key states and transitions. Then outline a test plan that covers each required scenario, using mocks for external dependencies and focusing on deterministic, isolated tests. Finally, discuss how you would structure the tests for readability and maintainability, and mention any edge cases or trade-offs.

Pro tip: Emphasize the importance of testing idempotency and state transitions, as these are critical in distributed systems like DoorDash's. Also, mention using test doubles (mocks/stubs) to simulate timeouts and retries without relying on real time delays.

1. Understand the system and requirements

Clarify the component under test, its responsibilities, and the expected behavior for each scenario. Identify inputs, outputs, and side effects.

2. Design test cases for each scenario

For each path (not-timed-out, timed-out refund, completed order, retry, duplicate execution), define the preconditions, actions, and expected outcomes. Consider edge cases like partial failures.

3. Set up test doubles and fixtures

Use mocks or stubs to simulate external services (e.g., payment gateway, database) and control timeouts. Ensure tests are isolated and fast.

4. Write and organize tests

Implement tests using a framework like JUnit or pytest, following Arrange-Act-Assert. Group related tests and use descriptive names.

5. Review and discuss trade-offs

Consider coverage, maintainability, and potential flakiness. Discuss how to handle asynchronous behavior and idempotency.

Key Points to Mention

  • Idempotency: ensuring duplicate executions do not cause double refunds or orders.
  • State transitions: verifying the order moves through correct states (e.g., pending, completed, refunded).
  • Mocking timeouts: using fake clocks or dependency injection to simulate timeouts without real delays.
  • Retry logic: testing that retries occur on transient failures and not on permanent ones.
  • Refund path: verifying that refunds are issued only when appropriate and that they are recorded correctly.
  • Test isolation: ensuring tests do not depend on external systems or shared state.

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

Q4

How would you extend the workflow to support a partial refund node that refunds either a percentage or a fixed amount?

System DesignTechnical Trade-offs
Author's notes

Pretty natural follow-up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the existing workflow and the requirements for partial refunds, including percentage vs fixed amount and idempotency. Then propose a design that abstracts refund calculation, integrates with the workflow engine, and handles edge cases like over-refunds and concurrency.

Pro tip: Emphasize idempotency and auditability: refunds are financial transactions, so every partial refund must be uniquely identifiable and traceable to prevent double refunds and simplify reconciliation.

1. Clarify Requirements and Constraints

Ask about the existing workflow, refund types (percentage/fixed), limits (e.g., cannot exceed original amount), and whether multiple partial refunds are allowed. Confirm idempotency and concurrency requirements.

2. Design the Refund Node Abstraction

Introduce a new node type that accepts refund parameters (type, value) and calculates the actual refund amount based on the original payment. Ensure it validates against remaining refundable balance.

3. Integrate with Workflow Engine

Extend the workflow definition to include the partial refund node, ensuring it can be triggered conditionally. Handle state management to track cumulative refunds per payment.

4. Address Edge Cases and Failure Modes

Cover scenarios like concurrent refunds, partial failures, retries, and idempotency. Discuss how to handle over-refund attempts and currency rounding.

5. Discuss Trade-offs and Scalability

Compare synchronous vs asynchronous processing, and consider how the design scales with high transaction volume. Mention monitoring and alerting for refund anomalies.

Key Points to Mention

  • Idempotency keys to prevent duplicate refunds
  • Validation to ensure refund amount does not exceed original payment minus previous refunds
  • State management for tracking cumulative refunds (e.g., database transaction or event sourcing)
  • Concurrency control (e.g., optimistic locking) to handle simultaneous refund requests
  • Audit logging for compliance and reconciliation
  • Error handling and retry mechanisms for partial failures

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

Q5

How would you add a cancel node for timed-out orders where payment has not yet been captured?

System Design
Author's notes

Short answer, basically the same shape as the refund node but routing logic checks whether capture happened.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and constraints, such as order timeout duration, payment authorization flow, and system scale. Then propose a high-level design that includes a scheduled job or event-driven mechanism to identify timed-out orders, check payment status, and trigger cancellation. Finally, dive into details like idempotency, consistency, and failure handling to ensure reliability.

Pro tip: Emphasize idempotency and exactly-once processing to avoid double cancellations or refunds, and discuss how you would handle race conditions between payment capture and cancellation.

1. Clarify Requirements

Ask about timeout duration, payment authorization vs. capture, order states, and expected scale. Confirm whether cancellation should be automatic or require manual intervention.

2. High-Level Design

Propose a system that periodically scans for timed-out orders or uses events (e.g., order created with TTL). Outline components: scheduler, order service, payment service, and notification service.

3. Detailed Flow

Describe the step-by-step process: detect timeout, verify payment not captured, call payment service to void authorization, update order status to cancelled, and notify customer/restaurant.

4. Handle Edge Cases

Discuss idempotency (using idempotency keys), race conditions (e.g., payment captured just before cancellation), retries, and dead-letter queues for failures.

5. Scalability & Monitoring

Explain how to scale (e.g., sharding, distributed cron), monitor success rates, and set up alerts for anomalies.

Key Points to Mention

  • Idempotency and exactly-once processing to prevent duplicate cancellations
  • Race condition handling between payment capture and cancellation
  • Use of a distributed scheduler or event-driven architecture (e.g., Kafka, SQS) for scalability
  • Integration with payment service to void authorization (not refund, since not captured)
  • Order state machine and consistency guarantees (e.g., transactional outbox pattern)
  • Monitoring, alerting, and dead-letter queues for failure recovery

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

Q6

When using an AI coding assistant, how do you limit unintended code changes and what does your review process look like before accepting generated code?

Technical Trade-offsAdaptability & Ambiguity
Author's notes

Wasn't expecting this one in a coding round.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Frame your answer around a risk-aware workflow: scope the AI's task tightly, generate in small increments, and treat every suggestion as untrusted until reviewed. Emphasize that your review process mirrors code review for a junior engineer—tests, diffs, and understanding before acceptance.

Pro tip: Mention that you sometimes ask the AI to explain its changes or write tests first, which forces you to validate behavior rather than just syntax. Also note that you keep AI-generated code in separate commits to make reverting easy.

1. Scope the request narrowly

Define a small, specific task for the AI (e.g., a single function or test) to minimize blast radius. Avoid vague prompts that could lead to broad, unintended edits.

2. Generate in isolation

Work in a separate branch or scratch file, and never let the AI modify critical paths directly. This contains changes and makes them easy to discard.

3. Review the diff line-by-line

Treat the output as a pull request from an unknown contributor: read every line, check for edge cases, security issues, and adherence to project conventions.

4. Validate with tests and static analysis

Run existing tests, add new ones for the generated code, and use linters/type checkers. If tests fail, iterate with the AI or fix manually.

5. Integrate incrementally

Commit small, logical chunks with clear messages, and monitor CI/CD. This allows quick rollback if issues arise in production.

Key Points to Mention

  • Use version control to isolate AI changes (branches, small commits).
  • Apply the same code review standards as for human-written code.
  • Leverage automated tests, linters, and type checkers as safety nets.
  • Understand the code before accepting it—never copy-paste blindly.
  • Consider security and performance implications of AI suggestions.
  • Document or comment on AI-assisted code for transparency and future maintenance.

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