system-design
How would you design a delivery app?
A delivery app has three users with three completely different needs: the customer ordering food, the restaurant preparing it, and the driver delivering i...
9 Mar 2024
A delivery app has three users with three completely different needs: the customer ordering food, the restaurant preparing it, and the driver delivering it. Get any one of those experiences wrong and the whole system breaks down.
I've worked on logistics systems where a 30-second delay in driver assignment meant a cold meal and a one-star review. Delivery apps are real-time coordination problems disguised as CRUD apps.
Functional Requirements
- User Accounts — registration, login, profile management. Social login for reduced friction. Address book for saved delivery locations.
- Product Browsing and Search — browse restaurant menus or product catalogs. Search by name, category, cuisine, dietary restriction. Filter by rating, distance, price, delivery time.
- Order Placement and Tracking — place orders, select delivery options (standard, express), and track delivery status in real-time on a map. Order confirmation, ETA updates, and delivery completion notifications.
- Payment Processing — support credit cards, digital wallets, cash on delivery. Integrate with Stripe or Adyen. Handle tips, promo codes, and refunds.
- Delivery Management — assign orders to drivers, optimize routes, provide turn-by-turn navigation, and let drivers update order status (picked up, en route, delivered).
Technical Requirements
- Scalable Infrastructure — dinner rush means 10x traffic in a 2-hour window. The system must handle peaks without degradation. Cloud-based auto-scaling is essential.
- Real-Time Communication — WebSockets or Firebase for live order tracking. Server-Sent Events for status updates. Push notifications for offline users.
- Geolocation Services — Google Maps API or Mapbox for location tracking, route optimization, ETA calculation, and geofencing (defining delivery zones).
- Payment Gateway — Stripe or PayPal integration with tokenization, encryption, and PCI-DSS compliance.
High-Level Design
Client Apps
Two separate apps:
- Customer app — browse, order, track, pay. Built with React Native or Flutter for cross-platform.
- Driver app — accept orders, navigate, update status. Optimized for use while moving — large buttons, voice feedback, minimal distraction.
Backend Services
- User Service — authentication, profiles, addresses.
- Catalog Service — restaurant/product listings, menus, pricing, availability.
- Order Service — order creation, status management, history.
- Matching Service — assigns orders to nearby available drivers. This is the most complex service — it considers driver location, current load, restaurant proximity, and delivery distance.
- Tracking Service — receives driver location updates (every 3-5 seconds), computes ETAs, and pushes updates to customers.
- Payment Service — handles charges, refunds, driver payouts, and tip distribution.
- Notification Service — push notifications, SMS, and email for order updates.
Database
- PostgreSQL — user profiles, order details, payment records. Needs ACID transactions for financial data.
- Redis — driver locations (geospatial queries with GEORADIUS), session data, rate limiting.
- Elasticsearch — restaurant and product search with filters and ranking.
Implement database sharding by region for scalability. Replicate for fault tolerance.

The Trade-Offs
Driver matching: nearest vs. optimal. Assigning the nearest driver is fast and simple. But it's not always optimal — a driver 2 minutes away but heading in the opposite direction might take longer than one 5 minutes away heading toward the restaurant. Optimal matching requires route calculation, which is slower. Most apps use a heuristic: nearest driver within a radius, filtered by heading direction.
Real-time tracking frequency. Updating driver location every second gives smooth map animation but generates massive traffic. Every 10 seconds saves bandwidth but makes the map jumpy. 3-5 second intervals are the sweet spot. Client-side interpolation smooths the visual gaps.
Centralized vs. regional architecture. A single backend works for one city. Multiple cities need regional deployments for low latency. But regional deployments mean data synchronization challenges if a user travels between regions.
Estimated delivery time accuracy. Users care deeply about ETA accuracy. Under-promise and over-deliver works psychologically. But if your ETA says 30 minutes and the food arrives in 15, the customer might not be ready. If it says 30 and arrives in 45, they're frustrated. The best systems show a range ("25-35 min") and narrow it as the delivery progresses.
The hardest part of a delivery app isn't the technology. It's the coordination. Three different users, unpredictable traffic, variable preparation times, and the physics of driving from point A to point B. The system design exists to make that coordination feel effortless.