Online Food Delivery Platform — System Design
1) Use Case & Problem Context
Users should be able to:
-
Browse restaurants near them
-
View menus (with frequent changes)
-
Build carts and see accurate pricing (tax/fees/promos)
-
Place orders and pay
-
Restaurant accepts or rejects (out of stock, substitutions)
-
Dispatch a courier and track delivery live
-
Handle spikes (lunch/dinner), refunds, cancellations, fraud
Key challenges:
-
High traffic bursts
-
Menu updates and item availability uncertainty
-
Distributed order lifecycle (multi-step workflow)
-
Real-time courier tracking
-
Reliability + idempotency (retries must not double-charge)
2) Core Requirements
Functional
-
Restaurant discovery by location
-
Menu browse (versioned)
-
Cart pricing (coupons, taxes, fees, tips)
-
Place order + payment authorization
-
Restaurant accept/reject + substitutions
-
Dispatch courier + ETA
-
Live tracking and notifications
-
Cancellations and refunds
Non-Functional
-
Low latency for browse/search
-
High availability for ordering/payment
-
Eventual consistency acceptable for tracking (seconds)
-
Strong observability and fraud controls
-
Scalable dispatch matching
3) High-Level Architecture
Services
-
Catalog/Search Service: restaurants + menus by geo
-
Cart/Pricing Service: cart + price breakdown engine
-
Order Service: order state machine + saga orchestration
-
Payment Service: auth/capture/refund
-
Restaurant Adapter: connects to restaurant POS/tablet
-
Dispatch Service: courier matching, offers, surge
-
Geo/Tracking Service: live courier location ingestion + queries
-
Notification Service: SMS/push/email + in-app events
-
Fraud/Risk Service: suspicious orders, test orders, chargeback defense
Text diagram
4) Catalog & Search Design
What we store
-
Restaurant metadata: geo, cuisine, rating, hours, price range
-
Menus: items, prices, modifiers, menu_version
-
Availability often dynamic (restaurants change stock)
Indexing approach (fast browse)
-
Denormalized searchable catalog by geo cells (city/zipcode/geohash)
-
Filters: cuisine, price, open now
-
Cache hot geo areas (downtown) heavily
Why denormalize?
Browse/search needs to be extremely fast and can tolerate slightly stale data.
5) Cart & Pricing (Where correctness matters)
Cart rules
-
Cart belongs to a restaurant (usually one restaurant per order)
-
Pricing is computed using a pricing engine
-
taxes, delivery fee, service fee, surge fee
-
discounts/coupons
-
tips (optional)
-
rounding rules
-
Menu changes handling
Menus change frequently, so cart must reference:
-
restaurant_id -
menu_version -
item SKU + selected modifiers
On checkout:
-
validate SKU still valid
-
reprice if menu_version changed
-
show user changes clearly
6) Order Lifecycle Using Saga (Core of the system)
Order Saga (typical states)
Why Saga?
Because ordering spans multiple systems:
-
Payments
-
Restaurant acceptance
-
Dispatch/couriers
Sagas allow:
-
step-by-step progression
-
compensations (refund/cancel) if a step fails
Compensation examples
-
Payment authorized but restaurant rejects → void/refund
-
Dispatch fails (no couriers) → cancel + refund
-
Courier cancels mid-way → re-dispatch or cancel
7) Ordering Data Flow (Step-by-step)
A) Place order
-
POST /order {cart_id, payment_method} -
Order Service creates
order=PENDING -
Calls Payment → authorize
-
Sends order to restaurant → accept/reject
-
If accepted → Dispatch service assigns courier
-
On courier assignment → status updates and tracking enabled
-
On delivered → Payment capture + final receipt
Text diagram
8) Dispatch & ETA (Matching couriers)
Matching approach (high level)
-
Partition space into geo cells
-
Maintain couriers in nearby cells with:
-
last location
-
capacity / current load
-
status
-
-
Score candidates by:
-
distance to restaurant
-
estimated pickup time
-
courier load / rating
-
delivery SLA
-
Surge handling
When demand > supply:
-
increase delivery fees
-
batch offers to couriers
-
expand search radius / relax constraints
Dispatch flow
-
Order ready-for-dispatch
-
Find eligible couriers near restaurant
-
Send offers (auction-like)
-
First accept wins → assignment created
9) Live Tracking (Real-time map)
How it works
-
Courier app sends location updates every few seconds
-
Ingest into Geo store (Redis GEO / TSDB)
-
Tracking API reads latest locations and returns route status
Tracking flow
Consistency:
-
Eventual (a few seconds delay acceptable)
10) Notifications
Send updates to:
-
Customer (push/SMS): order accepted, courier assigned, arriving, delivered
-
Restaurant: new order ticket/print
-
Courier: new assignment, pickup details
Important: notifications should be asynchronous and retryable.
11) Fraud & Safety (High level)
Common fraud patterns:
-
Fake/test orders
-
Stolen cards / chargebacks
-
Abnormal routes / courier collusion
-
Coupon abuse
Controls:
-
device fingerprinting + velocity limits
-
risk scoring before payment capture
-
suspicious order hold / manual review
-
courier route anomaly detection
12) Data Model (Simple)
restaurants
-
(id, geo_cell, hours, cuisine, menu_version)
menu_items
-
(restaurant_id, sku, price, modifiers, stock?)
orders
-
(id, user_id, restaurant_id, items[], price, status, created_at)
couriers
-
(id, status, last_location, capacity)
assignments
-
(order_id, courier_id, status, created_at)
events (optional)
-
(order_id, event_type, ts, payload)for audit/debug
13) APIs (Blog-level)
Catalog
-
GET /restaurants?geo=...&filters=... -
GET /restaurants/{id}/menu
Cart
-
POST /cart {restaurant_id, items, coupon} -
POST /cart/{id}/price→ price breakdown
Order
-
POST /order {cart_id, payment} -
GET /order/{id}
Dispatch (internal)
-
POST /assign {order_id}
Tracking
-
GET /track/{order_id}
14) Mermaid Diagram (Optional)
15) Interview Talking Points (What to highlight)
-
Saga and compensations (refund on failure)
-
Idempotency (avoid double charge/order)
-
Dispatch strategy + surge handling
-
Menu versioning + substitutions workflow
-
Cursor-based tracking updates
-
Fraud signals (coupon abuse, route anomalies)
-
Scalability: cache hot geo cells, async notifications
16) One-Minute Interview Summary (Memorable)
“Browse uses a denormalized geo-indexed catalog with heavy caching.
Checkout goes through cart pricing and then an order saga: payment auth → restaurant accept → dispatch courier → deliver → capture payment.
Dispatch uses geo-cell matching and scoring, and live tracking is powered by frequent courier location updates into a geo store.
Failures are handled by saga compensations like cancel + refund, and we add risk scoring and rate limits to reduce fraud.”
No comments:
Post a Comment