Core Entities
Restaurant: restaurant_id, name, address, geo_location, cuisine_type, is_open, prep_time_minutes, delivery_radius_km. MenuItem: item_id, restaurant_id, name, price_cents, category, is_available, customizations[]. Order: order_id, customer_id, restaurant_id, driver_id, status (PLACED, CONFIRMED, PREPARING, READY_FOR_PICKUP, PICKED_UP, DELIVERED, CANCELLED), items[], subtotal_cents, delivery_fee_cents, placed_at, estimated_delivery_at. Driver: driver_id, name, vehicle_type, current_location (lat/lng), status (OFFLINE, AVAILABLE, EN_ROUTE_TO_RESTAURANT, EN_ROUTE_TO_CUSTOMER), current_order_id, rating. DeliveryZone: zone_id, polygon (geofence), surge_multiplier.
Order Lifecycle
PLACED: customer submits the order. Validate items are available, restaurant is open, customer is in the delivery radius. Calculate delivery fee. Initiate payment (hold/authorize). CONFIRMED: payment authorized, restaurant notified via push/WebSocket. Restaurant sets estimated prep time. PREPARING: restaurant accepts and starts cooking. Start driver dispatch search (so a driver arrives near pickup time). READY_FOR_PICKUP: restaurant marks food ready. Assigned driver heads to restaurant. PICKED_UP: driver confirms pickup (scans QR or taps the app). Customer notified with live tracking link. DELIVERED: driver confirms delivery (GPS verification — must be within 100m of the drop address). Payment captured. Customer prompted for rating. CANCELLED: before PICKED_UP only. Release payment hold. Notify driver and restaurant.
Driver Dispatch Algorithm
Find the best available driver when an order is placed (or when the restaurant is nearly done preparing). Requirements: driver must be AVAILABLE (or finishing a delivery nearby), within a radius (start at 3km, expand to 10km if no match), vehicle type compatible with order size. Scoring: score = w1 * (1/distance_to_restaurant) + w2 * driver_rating + w3 * (1/current_active_orders). Assign the highest-scoring driver. Spatial indexing: store driver locations in a geospatial index (Redis GEOADD/GEORADIUS or PostGIS). Query returns drivers within radius sorted by distance. Reserve the driver (set status to ASSIGNED) before sending the offer. Offer timeout: driver has 30 seconds to accept. On decline or timeout: offer to the next best driver. Log acceptance rates for driver performance.
Real-Time GPS Tracking
Driver app sends GPS coordinates every 5 seconds while on an active order. Update path: Driver App -> API Gateway -> Location Service -> Redis (store latest location per driver_id) -> Pub/Sub (notify subscribers). Customer app subscribes to location updates for their order_id via WebSocket. Location Service publishes to a channel per order_id. Customer app receives updates and renders the driver position on a map. Location history is stored in a time-series table for ETA recalculation and post-delivery route analysis. Reduce battery drain: increase update interval to 15 seconds when the driver is stationary (detected by speed < 5km/h). Privacy: stop sharing driver location after delivery confirmation.
ETA Calculation
Delivery ETA = restaurant prep time + driver travel to restaurant + food handling buffer + driver travel to customer. Components: (1) Prep time: restaurant-provided estimate, learned from historical data per restaurant and hour of day. (2) Travel time: use a routing engine (Google Maps API, OSRM, internal map service) with real-time traffic. (3) Buffer: 2-3 minutes for handoff. Recalculate ETA every minute using the driver current GPS position and live traffic data. Display ETA as a range (“25-35 minutes”) to account for uncertainty. If ETA slips by more than 10 minutes: notify the customer proactively. Track ETA accuracy (predicted vs actual) per restaurant, driver, and time window to improve the model.
Surge Pricing
When demand exceeds driver supply in a zone, apply a surge multiplier to delivery fees. Compute zone-level demand/supply ratio every 5 minutes: ratio = pending orders in zone / available drivers in zone. Multiplier tiers: ratio 1-1.5x: no surge. 1.5-2x: 1.25x fee. 2-3x: 1.5x fee. 3x+: 2x fee. Show surge multiplier to customers before they place the order. Show drivers that a high-surge zone is nearby to attract more supply. Cap surge at 3x (regulatory and PR reasons). Surge multipliers are stored per DeliveryZone and refreshed every 5 minutes. The customer order stores the surge_multiplier_at_placement so the fee is locked in at order time.
{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “How do you dispatch drivers efficiently for food delivery?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Driver dispatch is a real-time assignment problem. When an order is placed: (1) Determine target pickup time = now + restaurant_prep_time. (2) Find drivers who can reach the restaurant by pickup time: query geospatial index (Redis GEORADIUS or PostGIS) for available drivers within expanding radius (start 3km, try 5km, 10km). (3) Score each candidate driver: score = w1/distance_to_restaurant + w2*driver_rating + w3*acceptance_rate. (4) Offer to the highest-scoring driver with a 30-second accept window. (5) On decline or timeout: offer to the next driver. Batch dispatch: for high-volume markets, run a global matching optimizer (Hungarian algorithm) every 10-30 seconds assigning all unassigned orders to available drivers — more efficient than sequential individual offers.”
}
},
{
“@type”: “Question”,
“name”: “How do you calculate accurate delivery ETAs?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “ETA = prep_time + driver_to_restaurant_travel + handoff_buffer + driver_to_customer_travel. Each component: (1) Prep time: restaurant-set estimate, validated against historical data per restaurant, meal type, and time of day. ML model predicts actual prep time from these features. (2) Travel times: routing engine (Google Maps Distance Matrix API or internal OSRM) with real-time traffic. (3) Handoff buffer: 2-3 minutes for parking, walking into restaurant, and food handoff. (4) Recalculate every 60 seconds using the driver current GPS position and live traffic. Show ETA as a 10-minute range (25-35 min) to buffer uncertainty. Track ETA accuracy: predicted vs actual across all orders. Expose per-restaurant average prep time in the merchant dashboard so restaurants can improve their estimates.”
}
},
{
“@type”: “Question”,
“name”: “How does real-time driver tracking work at scale?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Driver app sends GPS coordinates every 5 seconds while on an active order. Ingestion path: Driver App -> Load Balancer -> Location Service -> Redis (latest position per driver_id using SET with 30s TTL) -> Kafka (stream for analytics and ETA recalculation). Customer subscription: when a customer opens the tracking screen, their app establishes a WebSocket connection to the Location Service. The service subscribes to a Redis pub/sub channel for their order_id. On each driver update, the service pushes the new coordinates to all subscribed customers. At 100K concurrent active orders with 5-second update intervals = 20K location updates/second. Scale horizontally: shard the Location Service by order_id. Use connection stickiness (same server handles all connections for an order_id) to avoid cross-server message delivery.”
}
},
{
“@type”: “Question”,
“name”: “How do you handle order cancellations and partial refunds?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Cancellation policy depends on order status: (1) Before CONFIRMED: full refund, no penalty — restaurant has not started yet. (2) PREPARING: partial refund — restaurant has started cooking, charge 50% of food cost (covers ingredients). Notify the restaurant to stop. (3) After PICKED_UP: no refund for food — driver has the food. Delivery fee may be refunded if the driver cannot complete delivery. Refund processing: call the payment provider to issue a partial or full refund to the original payment method. Store a Refund record with reason, amount_cents, status. If restaurant cancels (out of stock): full customer refund, attempt to reassign to another restaurant if possible, notify the customer. Track cancellation rates by restaurant to identify supply issues. High-cancellation restaurants may be temporarily suspended.”
}
},
{
“@type”: “Question”,
“name”: “How does surge pricing work for delivery fees?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Surge pricing balances demand and driver supply by raising fees to attract more drivers and reduce order volume. Compute zone-level demand/supply ratio every 5 minutes: ratio = pending_orders_in_zone / available_drivers_in_zone. Map ratio to a multiplier: 1.0-1.5x ratio -> no surge; 1.5-2.0x -> 1.25x fee; 2.0-3.0x -> 1.5x fee; 3x+ -> 2x fee. The multiplier is applied to the base delivery fee (not the food price). Show the surge multiplier to customers before checkout with a transparent explanation. Store the multiplier on the order at placement time so it does not change mid-checkout. Show drivers high-surge zones on their map to attract supply. Cap surge at 2-3x (regulatory limits in some jurisdictions). Measure surge effectiveness by comparing driver supply response and order conversion rates at different multiplier levels.”
}
}
]
}
Asked at: DoorDash Interview Guide
Asked at: Uber Interview Guide
Asked at: Lyft Interview Guide
Asked at: Snap Interview Guide