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:

SubsystemWorkloadNeeds
Browse & searchRead-heavyCaching, geo lookup, denormalised catalog
Order coordinationWrite-heavy, statefulDurable 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 → delivered

This 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.