Food delivery platform inspired by DoorDash, Uber Eats and Swiggy: geo-filtered restaurant discovery, idempotent orders with a state machine, restaurant tablet push, courier location tracking in a geo store, automatic dispatch, live ETAs and capture-on-delivery payments. A teaching design.
See why one server listing everything and manual dispatch can't handle dinner rush.
What was missing: Nothing yet.
Why that's risky: Customers see restaurants that can't deliver to them, a retried order creates a duplicate, nobody knows where couriers are, and dinner traffic swamps one server.
What gets added: One server that lists every restaurant, places orders, and leaves courier assignment to staff.
Trade-offs: Fine for one town and a handful of couriers.
Show only restaurants that deliver to the customer, and never create an order twice.
What was missing: All restaurants were listed and retries duplicated orders.
Why that's risky: After ordering, nothing tells the restaurant or updates the customer.
What gets added: A discovery service backed by a geo index of restaurants and delivery areas, a menu service with a cache, a CDN for photos, and an order service that creates each order in a transaction keyed by an idempotency key.
Trade-offs: Menus are cached, so a sold-out item can show for a moment; the order service rechecks availability.
Move each order through its states and keep restaurant and customer informed.
What was missing: Orders were recorded but nobody acted on them.
Why that's risky: There's still no courier: someone has to find one manually.
What gets added: An order event stream of state changes, a push channel that sends new orders to restaurant tablets and collects 'accepted' and 'ready', and a notification worker that updates customers.
Trade-offs: Notifications follow state changes by a second or two.
Know where every courier is and assign each order automatically.
What was missing: No courier positions and no automatic assignment.
Why that's risky: Customers can't see where their courier is or when the food will arrive.
What gets added: Couriers' apps send GPS pings to a location service that keeps every online courier in a geo store; a dispatch worker finds nearby available couriers when an order is accepted, picks one by pickup ETA (batching orders heading the same way) and offers the job with a timeout.
Trade-offs: Dispatching when the restaurant accepts (not when the order is placed) avoids couriers waiting at the counter, at the risk of a short wait for a courier.
Show the courier on the map and an honest arrival time.
What was missing: Customers couldn't see progress.
Why that's risky: Payments aren't captured or paid out, and abuse and quality aren't watched.
What gets added: A tracking service showing the courier's live position, and an ETA service predicting prep and travel time from the restaurant's prep history, the courier's position and traffic.
Trade-offs: ETAs are re-estimated as the order progresses rather than fixed at checkout.
Charge and pay out correctly, block abuse, and watch delivery quality.
What was missing: Payments weren't captured, and nothing limited abuse or measured service quality.
Why that's risky: Remaining risk is regional: each city's dispatch should keep working if another region fails.
What gets added: A payment worker that captures the payment authorized at checkout once the order is delivered and pays out restaurants and couriers, a rate limiter, and monitoring of order success, dispatch time, acceptance rate and ETA accuracy.
Trade-offs: Capturing on delivery means a cancelled order is never charged, at the cost of rare failed captures.
Require an idempotency key from the client for checkout requests. Persist the key with the final order result. On retry, return the stored outcome. Ensure payment capture and order write are idempotent and use outbox/event logs for downstream publication.
Use a delivery service that batches nearby orders and available couriers. Maintain a priority queue by ETA/cost. Use a worker consuming assignment requests from a queue, with backoff and retries for contention. Keep courier location updates in memory for fast lookups.
Cache per-restaurant menus with short TTLs and invalidate on updates from the partner console. Use background refresh for top restaurants during peaks. Include ETags to avoid sending full payloads.
Isolate payment processing in a dedicated service behind strict network and data access controls. Tokenize card data; never store PANs directly. Use a compliant PSP. Keep the rest of the platform out of PCI scope.
You're in the middle of an interview session. Leaving now will end your current attempt.
Explore concept overviews, real-system examples, key tradeoffs, and interview talking points for each roadmap section.
You've conquered this phase. These are the skills you now own: