PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep
|Home/System Design/Uber

Design a Food-Delivery Backend (Uber Eats-style)

Last updated: Jun 24, 2026

Quick Overview

This system design question tests a candidate's ability to architect a large-scale, multi-actor backend involving geospatial matching, real-time data streaming, and distributed service coordination. It evaluates practical knowledge of scalable microservices, courier dispatch algorithms, and live tracking infrastructure — competencies commonly assessed for senior software engineering roles.

  • medium
  • Uber
  • System Design
  • Software Engineer

Design a Food-Delivery Backend (Uber Eats-style)

Company: Uber

Role: Software Engineer

Category: System Design

Difficulty: medium

Interview Round: Technical Screen

Design the backend for a food-delivery platform like Uber Eats. A customer opens the app, browses nearby restaurants, places an order from a menu, pays, and then watches the order progress in real time — the restaurant accepting and preparing it, a courier being assigned and picking it up, and the courier driving to the customer's address. Your design should cover the customer, the restaurant, and the courier as three distinct actors, and it should support order placement, courier dispatch/matching, and live order/courier tracking on a map. ```hint Decompose the actors and flows first Three actors (customer, restaurant, courier) and three core flows — **browse/order**, **dispatch/matching**, and **live tracking**. Treat them as separable subsystems with different read/write and latency characteristics rather than one monolith. ``` ```hint The hard subsystem is geospatial matching Courier-to-order assignment and "restaurants near me" are both **nearest-neighbor over a moving/streaming geo index**. Reach for a geospatial index (geohash / S2 / H3 cells, or PostGIS / a Redis geo set) plus a high-write-rate location-ingest path for courier pings. ``` ```hint Tracking is a fan-out streaming problem, not a request/response one Couriers emit frequent location updates; one customer needs the live position of exactly their courier. Think about an ingestion pipeline for pings plus a push channel (WebSocket / SSE) to the right subscriber, not polling a database on every render. ``` ### Constraints & Assumptions - Scale: assume ~10M daily active customers, ~500K active couriers and ~1M restaurants globally; peak ~5K orders/sec at meal rushes. - Courier devices send a location ping every 4–5 seconds while on an active trip → on the order of $10^5$–$10^6$ location writes/sec at peak. - Order placement is a strongly-consistent, transactional write (payment + inventory/availability); browsing and tracking tolerate eventual consistency. - Targets: restaurant feed loads in < 300 ms (p95); a courier's new location reaches the watching customer in < 2–3 s; dispatch assigns a courier within a few seconds of restaurant acceptance. - Single logical region per metro; cross-region traffic is rare (couriers don't cross metros). You may design per-city/per-region sharding. ### Clarifying Questions to Ask - What is the geographic scope — a single city, a country, or global? This drives sharding (per-metro vs. global) and the geo-index choice. - What are the latency/freshness expectations for live tracking — is 2–3 s staleness acceptable, or does the product need sub-second? - Is payment in scope, or do we assume an external payment service and only model the order/charge state machine around it? - How sophisticated must dispatch be — nearest-available courier, or a batched optimizer that considers ETA, multi-pickup batching, and courier earnings fairness? - What are the consistency requirements on the order lifecycle — can we tolerate a brief window where the customer and restaurant see slightly different states? - What's the read/write split we should optimize for (browsing is read-heavy; tracking is write-heavy)? ### Part 1 — Order placement and the order lifecycle Design the write path for placing an order: how a customer's cart becomes a paid, accepted, in-progress order, and how the order's state machine is modeled and kept consistent across the customer, the restaurant, and (later) the courier. Address payment, idempotency, and what happens when the restaurant rejects or is offline. ```hint Model the order as an explicit state machine States like `CREATED → PAYMENT_AUTHORIZED → RESTAURANT_ACCEPTED → PREPARING → COURIER_ASSIGNED → PICKED_UP → DELIVERED`, plus `REJECTED`/`CANCELLED` terminal branches. Persist transitions in a transactional store; emit an event per transition for downstream subsystems. ``` ```hint Make checkout idempotent and decouple payment from acceptance Use an idempotency key per checkout so a retried "Place order" tap doesn't double-charge. Authorize (not capture) the payment at placement; capture on restaurant acceptance, and auto-void/refund on rejection or timeout. ``` #### What This Part Should Cover ```premium-lock What This Part Should Cover ``` ### Part 2 — Browse / discovery: "restaurants near me" Design the read path for the customer's home feed and search: showing open, deliverable restaurants near the customer's location, with menus, ranking, and acceptable latency under heavy read load. ```hint This is a geo-filtered, cached, read-heavy path Index restaurants by a geospatial scheme (geohash / S2 / H3 cell, or PostGIS) so "near me" is a bounded cell lookup, not a full scan. Layer caching (CDN/edge for menus, per-cell feed caches) because the same city cells are queried constantly. ``` #### What This Part Should Cover ```premium-lock What This Part Should Cover ``` ### Part 3 — Courier dispatch and matching Design how, once a restaurant accepts an order, the system selects and assigns a courier. Cover how courier locations and availability are tracked, how a candidate set is found, how one is chosen, and how races (two orders competing for one courier) are resolved. ```hint Maintain a live geo-index of available couriers Keep an in-memory / Redis geo set of available couriers keyed by cell, updated from the location-ping stream. Matching = query couriers within an expanding radius of the restaurant, score by ETA/load, then atomically reserve one. ``` ```hint Assignment must be atomic and reservation-based to avoid double-booking Use an atomic claim (compare-and-set / distributed lock / a transactional `reserved` flag with TTL) so a courier offered an order is removed from the candidate pool; if they decline or time out, release and re-dispatch. ``` #### What This Part Should Cover ```premium-lock What This Part Should Cover ``` ### Part 4 — Live tracking of the order and courier Design the real-time tracking experience: the customer watches the courier move on a map and sees order-status changes; the courier app streams location and receives the next instruction. Cover ingestion of high-frequency location pings and pushing the right updates to the right customer with low latency. ```hint Separate the high-write ingest path from the fan-out path Ingest pings through a streaming buffer (e.g. Kafka / a queue) into a hot location store; push to the watching customer over a persistent connection (WebSocket / SSE) keyed by the order's courier — never have clients poll the DB per frame. ``` ```hint Only one customer cares about each courier ping Route a courier's location to subscribers of that courier's active order (a pub/sub topic per order or per courier). Smooth/throttle on the client; you don't need to persist every ping forever — recent positions in a fast store, downsampled history if needed. ``` #### What This Part Should Cover ```premium-lock What This Part Should Cover ``` ### What a Strong Answer Covers ```premium-lock What a Strong Answer Covers ``` ### Follow-up Questions - How would you batch a courier picking up two nearby orders on one trip (Part 3), and what changes in matching and tracking? - A metro's dispatcher region gets a sudden surge (a stadium event) and there are no couriers nearby. How does the system degrade gracefully (Parts 3 & 1)? - How do you guarantee a customer is never double-charged and a courier is never double-assigned even under network retries and partial failures (Parts 1 & 3)? - Couriers report a "ghost" effect where their dot on the customer's map jumps around. What in your ingest/push design (Part 4) could cause this and how would you fix it?

Quick Answer: This system design question tests a candidate's ability to architect a large-scale, multi-actor backend involving geospatial matching, real-time data streaming, and distributed service coordination. It evaluates practical knowledge of scalable microservices, courier dispatch algorithms, and live tracking infrastructure — competencies commonly assessed for senior software engineering roles.

Related Interview Questions

  • Design a Real-Time Chat System - Uber (medium)
  • Design a Distributed Logging System - Uber (medium)
  • Design a Stock Trading Platform - Uber (medium)
  • Design an Uber Eats Cart Service - Uber (medium)
  • Design A URL Shortener - Uber (medium)
Uber logo
Uber
Jun 23, 2026, 12:00 AM
Software Engineer
Technical Screen
System Design
0
0

Design the backend for a food-delivery platform like Uber Eats. A customer opens the app, browses nearby restaurants, places an order from a menu, pays, and then watches the order progress in real time — the restaurant accepting and preparing it, a courier being assigned and picking it up, and the courier driving to the customer's address. Your design should cover the customer, the restaurant, and the courier as three distinct actors, and it should support order placement, courier dispatch/matching, and live order/courier tracking on a map.

Constraints & Assumptions

  • Scale: assume ~10M daily active customers, ~500K active couriers and ~1M restaurants globally; peak ~5K orders/sec at meal rushes.
  • Courier devices send a location ping every 4–5 seconds while on an active trip → on the order of 10510^5105 – 10610^6106 location writes/sec at peak.
  • Order placement is a strongly-consistent, transactional write (payment + inventory/availability); browsing and tracking tolerate eventual consistency.
  • Targets: restaurant feed loads in < 300 ms (p95); a courier's new location reaches the watching customer in < 2–3 s; dispatch assigns a courier within a few seconds of restaurant acceptance.
  • Single logical region per metro; cross-region traffic is rare (couriers don't cross metros). You may design per-city/per-region sharding.

Clarifying Questions to Ask

  • What is the geographic scope — a single city, a country, or global? This drives sharding (per-metro vs. global) and the geo-index choice.
  • What are the latency/freshness expectations for live tracking — is 2–3 s staleness acceptable, or does the product need sub-second?
  • Is payment in scope, or do we assume an external payment service and only model the order/charge state machine around it?
  • How sophisticated must dispatch be — nearest-available courier, or a batched optimizer that considers ETA, multi-pickup batching, and courier earnings fairness?
  • What are the consistency requirements on the order lifecycle — can we tolerate a brief window where the customer and restaurant see slightly different states?
  • What's the read/write split we should optimize for (browsing is read-heavy; tracking is write-heavy)?

Part 1 — Order placement and the order lifecycle

Design the write path for placing an order: how a customer's cart becomes a paid, accepted, in-progress order, and how the order's state machine is modeled and kept consistent across the customer, the restaurant, and (later) the courier. Address payment, idempotency, and what happens when the restaurant rejects or is offline.

What This Part Should Cover Premium

Part 2 — Browse / discovery: "restaurants near me"

Design the read path for the customer's home feed and search: showing open, deliverable restaurants near the customer's location, with menus, ranking, and acceptable latency under heavy read load.

What This Part Should Cover Premium

Part 3 — Courier dispatch and matching

Design how, once a restaurant accepts an order, the system selects and assigns a courier. Cover how courier locations and availability are tracked, how a candidate set is found, how one is chosen, and how races (two orders competing for one courier) are resolved.

What This Part Should Cover Premium

Part 4 — Live tracking of the order and courier

Design the real-time tracking experience: the customer watches the courier move on a map and sees order-status changes; the courier app streams location and receives the next instruction. Cover ingestion of high-frequency location pings and pushing the right updates to the right customer with low latency.

What This Part Should Cover Premium

What a Strong Answer Covers Premium

Follow-up Questions

  • How would you batch a courier picking up two nearby orders on one trip (Part 3), and what changes in matching and tracking?
  • A metro's dispatcher region gets a sudden surge (a stadium event) and there are no couriers nearby. How does the system degrade gracefully (Parts 3 & 1)?
  • How do you guarantee a customer is never double-charged and a courier is never double-assigned even under network retries and partial failures (Parts 1 & 3)?
  • Couriers report a "ghost" effect where their dot on the customer's map jumps around. What in your ingest/push design (Part 4) could cause this and how would you fix it?

Solution

Show

Submit Your Answer to Earn 20XP

Sign in to leave a comment

Loading comments...

Browse More Questions

More System Design•More Uber•More Software Engineer•Uber Software Engineer•Uber System Design•Software Engineer System Design
PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.