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.
Asked at: DoorDash Interview Guide
Asked at: Uber Interview Guide
Asked at: Lyft Interview Guide
Asked at: Snap Interview Guide