Question Breakdowns
Local Delivery Service
A worked system design: show nearby stores, promise accurate delivery windows, and coordinate orders between customers, stores, and couriers in real time.
A local delivery service (think grocery or food delivery) lets a customer browse nearby stores, place an order, and watch it move from store to door. The interesting tension is between a read-heavy browsing experience and a write-heavy, real-time order-coordination problem — two very different workloads in one product. We'll borrow from Proximity Search and Multi-step Processes.
1. Requirements
Functional:
- Customer sees stores/items available near their location.
- Customer places an order; the store prepares it; a courier delivers it.
- Everyone sees order status update in real time.
Non-functional:
- Low-latency browsing (read-heavy, the funnel's top).
- Accurate availability — don't sell an item the store just ran out of.
- Real-time tracking of the order and courier.
- Reliable orchestration — an order is a multi-party, multi-step transaction that must not get stuck.
2. Two subsystems
Split the problem by workload — this framing alone is strong signal:
| Subsystem | Workload | Needs |
|---|---|---|
| Browse & search | Read-heavy | Caching, geo lookup, denormalised catalog |
| Order coordination | Write-heavy, stateful | Durable workflow, real-time updates |
3. Browse: nearby stores and availability
Finding stores near the customer is a geospatial query — index stores by location (geohash / quadtree) and fetch those within a radius. The store catalog (items, prices) is read constantly and changes rarely, so it's heavily cached (Scaling Reads).
Availability is the subtle part: inventory changes as orders come in. Keep a live per-store inventory count (in Redis) and decrement it at order time; treat the cached catalog as "what's on the menu" and the live count as "what's actually in stock right now."
4. The order is a workflow
An order passes through stages with real-world actors between them:
placed → store accepts → store preparing → courier assigned →
picked up → en route → deliveredThis is a long-running, multi-step process: each step can take minutes, can fail (store rejects, no courier available), and must be durable (a server restart can't lose an in-flight order). A state machine backed by a durable store — or a workflow engine like Temporal — models this cleanly, with timeouts and compensating actions (refund if the store cancels after charging).
5. Reserving inventory (contention)
When a customer checks out, the items must be reserved so two customers can't buy the last unit. This is a contention problem: atomically decrement the live inventory count at reservation time (an atomic Redis op or a conditional DB update), and release the reservation if checkout is abandoned via a TTL.
6. Real-time tracking
Both the customer and the store need live status; the customer also wants the courier's moving location. Status changes are pushed over a real-time channel (WebSocket/SSE). The courier's GPS pings stream in frequently — write them to a fast store and push the latest position to the watching customer; you don't need to durably keep every ping forever.
7. Deep dives
- Courier assignment: matching an order to the best nearby courier is itself a proximity + optimisation problem — find couriers near the store, pick by ETA/load.
- Surge / peak: dinnertime is a thundering herd; the order pipeline runs off a queue so spikes buffer instead of toppling stores.
- Consistency: browsing can be eventually consistent (a stale menu is fine); inventory reservation and payment must be strongly consistent.
- Idempotency: a retried "place order" must not create two orders — use an idempotency key.
What to emphasise
Separate the two workloads, then name the order as a durable workflow:
"I'd split this into a read-heavy browse path and a write-heavy order path. Browsing is a geo query for nearby stores over a heavily cached catalog, with live inventory counts in Redis so we don't oversell. The order itself is a durable multi-step workflow — placed, accepted, prepared, picked up, delivered — with timeouts and compensation, which I'd model with a state machine or a workflow engine so an in-flight order survives failures. Status and courier location stream to the customer over a real-time channel, and checkout reserves inventory atomically to handle contention on the last unit."
Next up: Ticket Booking — contention on a fixed set of seats.
