Marketplaces, an interactive architecture walkthrough
Food delivery platform: how the architecture works
How a food delivery platform runs each order as a durable state machine, tracks couriers in a geo index, and times dispatch to when food is ready.
This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate.
Interactive diagram
Overview
A food delivery platform connects three groups through one order: customers who choose and pay, restaurants that cook, and couriers who pick up and deliver. The order is a state machine, placed, accepted, courier assigned, picked up, delivered, run by a durable workflow that holds timers and retries, so a crash or a missing response does not leave an order stuck.
Discovery filters restaurants by delivery zone and shows an estimate built from prep time plus road travel time. Couriers send location pings into a geospatial index, and dispatch picks a courier whose arrival lines up with when the food will be ready, sometimes batching two nearby orders. Payment is authorised at checkout and captured only after delivery. This is a simplified learning design, not any company's production system.
Trade-offs and what changes at scale
Dispatching instantly is simple but often sends couriers to wait at restaurants, while waiting to batch and time assignments improves efficiency at the cost of a short delay and more complex logic. Location pings dominate write volume, so only the latest position is kept in memory and history goes to a stream. ETAs depend on prep times the platform does not control, so they are learned per restaurant and time of day. At larger scale the system is split by city or region, since orders, couriers and restaurants rarely interact across them.
How it works, step by step
The walkthrough above, as text. Each step lights up the components named under it.
The Customer App sends the delivery address, and Restaurant Search queries the Search Index for restaurants that are open and deliver to that zone. Filtering by delivery zone first keeps results to places that can actually deliver.
For each result, the ETA Service adds the restaurant's typical prep time to a road travel time from the Routing Engine. Showing a realistic time up front reduces cancellations later.
Cart & Pricing recomputes the cart from current menu prices, delivery fee and promotions on every change. Prices are never trusted from the client.
Placing the order makes the Order Service lock in the final price and write the order to the Order DB as "placed" with an idempotency key. A double tap on the button returns the same order instead of creating two.
The Order Workflow authorises the payment and then waits durably for each next event, with timeouts such as cancelling if the restaurant does not accept within five minutes. The card is only captured after delivery, so a cancelled order just releases the hold.
The Restaurant Tablet shows the new order, and accepting it moves the order to "accepted" with a prep-time estimate. That estimate decides when a courier should arrive, not just whether one is needed.
Every few seconds the Courier App sends a location ping, and the Location Service updates the courier's position in the Courier Geo Index. Only the latest position is kept there; the history goes to the event stream.
The Dispatch Service finds available couriers near the restaurant, gets road travel times, and picks one whose arrival matches when the food will be ready. Waiting a short moment to batch nearby orders often gives better assignments than matching each order instantly.
The offer is sent to the courier through Courier Events, and if it is declined or times out the Dispatch Service tries the next candidate. Every offer and response is recorded, so dispatch decisions can be reviewed later.
Once a courier is assigned, the Tracking Gateway forwards that courier's pings to the customer over a WebSocket. Only the customer of the active order receives the position, and only until delivery.
Each state change in the Order Workflow triggers a push or SMS through the Notification Service. Customers who closed the app still hear when the food is picked up and delivered.
Orders and courier events load into the Analytics Store, where actual prep and travel times are compared with the estimates. Those comparisons are what make the next ETA and dispatch decisions more accurate.
Sequence diagram
The same walkthrough as a UML sequence diagram, one lane per layer or group (20 components in all), left to right in the order a request reaches them, numbered by step. A loop on a lane is a step that stays inside that group. Solid arrows are synchronous calls, dashed are asynchronous.
Key components
Appslayer
- Courier App: location pings, offers, proof of delivery
- Customer App: browse, order, track delivery
- Restaurant Tablet: accept orders, mark ready
Discoverydomain
- ETA Service: prep time plus travel time estimate
- Restaurant Search: open restaurants near the address
- Routing Engine: road travel times between points
- Search Index: menus, cuisine, delivery zones (elasticsearch)
Orderingdomain
- Cart & Pricing: menu prices, fees, promotions
- Order DB: orders and state history (postgresql)
- Order Service: order state machine
- Order Workflow: durable timers, retries, compensation
- Payment Provider: authorise, then capture on delivery
Courier Dispatchdomain
- Courier Events: pings, offers, status changes (kafka)
- Courier Geo Index: available couriers by location (redis)
- Dispatch Service: batches orders, picks couriers
- Location Service: ingests courier pings
Tracking & Notificationsdomain
- Notification Service: push and SMS updates
- Tracking Gateway: live courier position to customers (websocket)
Analytics Store
- Analytics Store: prep times, delivery times, demand (clickhouse)
API Gateway
- API Gateway: auth, rate limits, routing
Sources
Public writing this explainer draws on. Read these for what the real systems actually do.
Make it yours
Copy this diagram and its walkthrough into your own workspace, then change anything: swap Postgres for DynamoDB, add a cache, rewrite the narration. Free, and it uses no AI credits.
Related walkthroughs
- Ride-hailing platformHow a ride-hailing platform streams driver locations, matches a rider to a nearby driver, prices the trip with surge, and takes payment.
- Ticket booking with seat reservationHow a ticketing system sells each seat once under heavy demand: waiting room, cached seat map, time-limited holds, conditional updates and safe payment.
- E-commerce checkout and inventoryHow an online store turns a cart into an order: stock reservation, idempotent payment, a saga with compensation, and reliable order events.
This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate. Real systems differ in the details. Browse the library.