Your Dashboard
Interview Coaching
Learn
System Design
ML System Design
Code
Behavioral
Salary Negotiation
Interview Guides
Design and implement Dasher payout calculation system
Asked at:
Doordash
DESCRIPTION
Design an API that calculates total payout for a driver based on their delivery events. Each delivery has events (accepted, cancelled, delivered) with timestamps, and payment is calculated using fixed rates plus bonuses based on concurrent deliveries. For example, if a driver has 2 ongoing deliveries when accepting a new one, they earn a higher rate for that delivery.
Input:
Output:
Explanation: Single delivery with base rate, no bonus multiplier applied
Constraints:
- Each accepted delivery has a corresponding completion event (delivered or cancelled)
- Events are provided with timestamps and delivery IDs
- Payment calculated per delivery based on concurrent delivery count at acceptance time
- Handle one driver at a time with mock data from dependent APIs
Understanding the Problem
The core challenge is tracking concurrent deliveries at each acceptance event to determine the correct bonus multiplier. You must process events chronologically to maintain an accurate count of ongoing deliveries (accepted but not yet completed). The payout for each delivery is locked in at acceptance time based on how many other deliveries were active. This requires careful state management to track which deliveries are in-flight and applying the correct rate formula when calculating final payout.
Building Intuition
A naive approach might calculate payout by simply counting total deliveries and applying an average rate, but this ignores the temporal aspect of concurrent deliveries. The better approach is to process events chronologically, maintaining a running count of active deliveries and capturing the multiplier at each accepted event. For example, if delivery D1 is accepted (count=0), then D2 accepted (count=1), then D1 delivered, D2's payout uses the higher rate even though D1 finished first.
This pattern applies to any time-based incentive system where rates depend on current workload or capacity. Real-world applications include surge pricing, capacity-based bonuses, and dynamic rate calculations in gig economy platforms. Understanding event-driven state tracking is essential for building accurate financial systems.
Common Pitfalls
Implementation
Event Processing and State Tracking
Process delivery events chronologically to maintain accurate concurrent delivery counts. Use a state machine approach where accepted events increment the active count and store the current multiplier, while delivered/cancelled events decrement the count. Track each delivery's locked-in rate in a map keyed by delivery ID. For example, when processing {id: 'D2', status: 'accepted'} with 1 active delivery, store multiplier=1.5 for D2, which persists even as other deliveries complete.
def process_events(events):events_sorted = sorted(events, key=lambda e: e['timestamp'])active_count = 0delivery_multipliers = {}for event in events_sorted:delivery_id = event['id']status = event['status']if status == 'accepted':multiplier = get_multiplier(active_count)delivery_multipliers[delivery_id] = multiplieractive_count += 1elif status in ['delivered', 'cancelled']:active_count -= 1return delivery_multipliers
Payout Calculation Logic
Calculate final payout by iterating through completed deliveries and applying their stored multipliers to the base rate. Only include deliveries with delivered status in the sum, ignoring cancelled ones. The formula is payout = base_rate * (1 + bonus_factor * concurrent_count) where concurrent_count is captured at acceptance time. For instance, a delivery accepted with 2 concurrent deliveries and base_rate=$10, bonus_factor=0.25 yields $10 * (1 + 0.25*2) = $15.
def calculate_payout(deliveries, base_rate, bonus_factor):total_payout = 0.0for delivery in deliveries:if delivery['status'] == 'delivered':concurrent_count = delivery['concurrent_count']payout = base_rate * (1 + bonus_factor * concurrent_count)total_payout += payoutreturn total_payout
API Design and Data Integration
Structure the API to accept delivery events from mock dependent services and return total payout for a single driver. Use dependency injection for the mock data source to enable testing and future integration with real APIs. The endpoint should validate that all accepted deliveries have corresponding completion events and handle edge cases like empty event lists or missing timestamps. Return a structured response with total payout and optionally a breakdown per delivery for debugging purposes.
from typing import Protocol, List, Dict, Anyfrom dataclasses import dataclass@dataclassclass PayoutResponse:total_payout: floatbreakdown: List[Dict[str, Any]]class DeliveryDataSource(Protocol):def get_delivery_events(self, driver_id: str) -> List[Dict[str, Any]]:...class PayoutAPI:def __init__(self, data_source: DeliveryDataSource):self.data_source = data_sourcedef calculate_payout(self, driver_id: str) -> PayoutResponse:events = self.data_source.get_delivery_events(driver_id)if not events:return PayoutResponse(total_payout=0.0, breakdown=[])self._validate_events(events)breakdown = self._compute_breakdown(events)return PayoutResponse(total_payout=sum(d['payout'] for d in breakdown), breakdown=breakdown)def _validate_events(self, events: List[Dict[str, Any]]) -> None:accepted = {e['delivery_id'] for e in events if e['status'] == 'accepted'}completed = {e['delivery_id'] for e in events if e['status'] in ('delivered', 'cancelled')}if accepted != completed:raise ValueError('Mismatched accepted and completion events')
What We've Learned
- Pattern: Event-driven state tracking with temporal locking captures time-sensitive business rules accurately
- Use Case: Apply to any system where rates/bonuses depend on real-time workload or capacity metrics
- Design: Separate event processing logic from payout calculation for testability and maintainability
- Debugging: Store intermediate state (multipliers per delivery) to enable audit trails and troubleshooting
Problems to Practice
The Dasher payout system requires processing delivery events with timestamps, which are essentially intervals. This lesson teaches how to work with time-based intervals, sort them, and handle overlapping periods - crucial for tracking concurrent deliveries and calculating bonuses based on the number of ongoing deliveries.
medium
This problem directly applies to the payout calculation system where you need to track overlapping delivery periods. Understanding how to merge and process intervals helps determine how many deliveries are ongoing at any given time, which is essential for calculating the bonus factors mentioned in the problem.
hard
This problem involves processing multiple schedules (similar to multiple delivery events) and finding gaps or overlaps. The technique of tracking concurrent intervals across different entities mirrors the challenge of calculating payouts based on how many deliveries a driver has ongoing simultaneously.
Question Timeline
See when this question was last asked and where, including any notes left by other candidates.
Early October, 2025
Doordash
Senior
Early October, 2025
Doordash
Senior
Late August, 2025
Doordash
Mid-level
Comments
Hello Interview Premium
Your account is free and you can post anonymously if you choose.