Design a Food Delivery System
Understanding the Problem
Food delivery platforms like DoorDash, UberEats, and Grubhub connect three parties: customers who want food, restaurants that prepare it, and drivers who deliver it. This three-sided marketplace is what makes this system uniquely challenging.
Functional Requirements:
- Customers can browse nearby restaurants, view menus, and place orders.
- Restaurants receive orders, confirm them, and update preparation status.
- The system dispatches the best available driver to pick up and deliver the order.
- Real-time tracking of delivery progress (driver location on map).
- Customers and drivers can rate each other after delivery.
Non-Functional Requirements:
- Low latency: Order placement must complete in <2 seconds.
- Real-time tracking: Driver GPS updates every 3-5 seconds, visible to customers in near real-time.
- Peak handling: Must handle lunch and dinner rush spikes without degradation.
- ETA accuracy: Estimated delivery time should be within 5 minutes of actual delivery.
Estimation
Let's size this system for a large-scale platform:
- 10M orders per day β that's ~115 orders/second average.
- 1M restaurants on the platform, ~200K active at any time.
- 500K active drivers β location updates every 4 seconds = 125K GPS writes/second.
- Peak load: Lunch (11am-1pm) and dinner (6-8pm) see 3-5x average traffic β ~5,000 orders/minute at peak.
- 1M concurrent tracking sessions β customers watching their delivery on the map.
- Storage: Each order ~2KB (items, addresses, status history). 10M/day Γ 365 Γ 2KB β 7 TB/year.
The key bottleneck is the real-time component: matching drivers, tracking locations, and predicting ETAs β all under tight latency budgets during peak hours.
Order Flow
The lifecycle of a food delivery order goes through several stages:
- Customer places order: Selects restaurant, adds items to cart, confirms payment. The order is created in the system.
- Restaurant confirms: Restaurant receives the order notification, confirms acceptance, and provides an estimated prep time (e.g., 20 minutes).
- Dispatch matches driver: The dispatch service finds the best available driver based on proximity, current load, and restaurant prep time. It may pre-dispatch before food is ready.
- Driver picks up: Driver arrives at restaurant, confirms pickup. Status updates flow to the customer in real-time.
- Delivery + tracking: Driver navigates to customer. GPS updates flow every few seconds. Customer sees the driver on a live map with a dynamic ETA.
Each transition triggers notifications to all relevant parties β the customer, restaurant, and driver all stay informed throughout.
Dispatch Algorithm
Driver matching is the heart of the system β it's an optimization problem balancing multiple factors:
- Driver proximity: How far is the driver from the restaurant? Uses geospatial indexing (like a geohash or quadtree) to find nearby drivers efficiently.
- Restaurant prep time: No point sending a driver immediately if food takes 25 minutes. Time the dispatch so the driver arrives just as food is ready.
- Route distance: Factor in road network distance, not just straight-line. A driver 1 mile away across a highway might take longer than one 2 miles away on surface streets.
- Driver current load: Is the driver already carrying another order? Batching is possible but adds complexity.
The dispatch engine scores available drivers and assigns the best match. This is similar to ride-sharing dispatch but with the added variable of restaurant prep time. The system may pre-dispatch β assign a driver early so they're en route to the restaurant just as food is ready.
ETA Prediction and Real-Time Tracking
ETA prediction uses an ML model trained on historical data:
- Prep time prediction: Based on restaurant's historical prep times, current order volume, time of day, and order complexity.
- Drive time prediction: Road network routing + live traffic data + time of day patterns.
- Total ETA: prep_time + driver_to_restaurant + restaurant_to_customer + buffer.
Real-time tracking works through continuous GPS updates:
- Driver app sends GPS coordinates every 3-5 seconds.
- Updates flow to a Driver Location Cache (Redis with geospatial support) β not the main database.
- Customer's tracking screen polls or receives WebSocket pushes with the latest position.
- ETA is dynamically recalculated as the driver progresses.
Order batching: When a driver can efficiently pick up multiple orders from nearby restaurants, the system batches them. This increases driver utilization but requires careful ETA management β the second customer's delivery is slightly delayed.