Design an Uber Eats Cart Service
Company: Uber
Role: Software Engineer
Category: System Design
Difficulty: medium
Interview Round: Onsite
Design the **shopping cart service** for a food-delivery platform similar to Uber Eats.
The service lets a customer add, update, and remove menu items from a cart before checkout. A cart is associated with one customer and typically one merchant/restaurant. Your design should cover:
- **Core user flows:** create cart, add item, update quantity, remove item, view cart, and submit the cart to checkout.
- **Menu modeling:** item options, modifiers, prices, taxes, fees, promotions, and availability.
- **Data model and APIs.**
- **Consistency** between the cart and the menu, pricing, inventory/availability, and checkout services.
- **Scalability, reliability, and failure handling.**
- **Edge cases:** restaurant closing, price changes, unavailable items, multiple devices, and abandoned carts.
Walk through the full design at a senior-engineer level: clarify the scope, size the system, propose a data model and API surface, then reason explicitly about where the system must be strongly consistent versus where it can be eventually consistent.
```hint Where to start
Decide what the Cart Service actually *owns*. Treat menu metadata, authoritative pricing/tax, promotions, restaurant hours, and inventory as separate services the cart **consumes**. The cart owns only mutable pre-checkout state — that boundary drives everything else.
```
```hint Consistency split — the core insight
You cannot keep the cart, menu, pricing, and inventory transactionally consistent in real time without crushing latency. So which moments in a cart's life actually *need* to be correct-to-the-cent, and which can tolerate a stale estimate? Let that distinction decide where strictness lives.
```
```hint Concurrency & retries
There's more than one concurrency problem hiding here — creating a *first* cart is a different situation from editing one that already exists, and they don't have the same defense. Separately, ask what makes a *retried* request safe to apply more than once.
```
```hint Abandoned carts
"Abandoned" isn't one thing — a cart left for a week and a cart untouched for an hour want very different responses on very different timescales. Ask whether one mechanism can realistically fire both, and what each would have to react to.
```
### Constraints & Assumptions
- One cart maps to **one user and one restaurant**; browsing a second restaurant yields a separate cart (or prompts the user to clear the first). Multi-restaurant "group" baskets are out of core scope.
- Treat scale as roughly **tens of millions of DAU**, on the order of **~10M active carts/day**, with **reads dominating writes ~10:1** and traffic concentrated in lunch/dinner peaks. (State your own numbers; these are illustrative, not authoritative.)
- The cart may store **price/availability estimates**; authoritative pricing, tax, and inventory are owned by other services.
- **Out of scope:** payment-processing internals, the order lifecycle after order creation, the menu CMS, and delivery/ETA estimation — the cart *consumes* those.
### Clarifying Questions to Ask
- What is the read:write ratio and the expected peak QPS, and what are the latency SLOs for a cart view versus a cart mutation?
- Is multi-restaurant ("group order") cart support in scope, or strictly one restaurant per cart?
- Does any menu item have *true* scarcity (limited stock that must be reserved), or is availability just an open/sold-out flag re-checked at checkout?
- Who owns authoritative pricing/tax/fees and promotions — does the cart compute anything itself, or only cache estimates?
- How long should an unconverted cart persist, and is there a re-engagement / abandoned-cart reminder requirement?
- How aggressively do clients retry on flaky networks, and is exactly-once semantics for `add`/`checkout` required?
### What a Strong Answer Covers
- A crisp **scope and ownership boundary**: what the Cart Service owns vs. what it calls out to.
- **Functional + non-functional requirements**, with explicit latency/availability targets and a stated read:write ratio.
- **Back-of-the-envelope sizing** (QPS at peak, storage/working-set) that justifies the storage and caching choices.
- A **data model** for the cart aggregate (items, modifiers, pricing snapshot, version) with a chosen partition key and access patterns.
- A clean **API surface** with idempotency and optimistic-concurrency parameters, and meaningful status codes (version conflict, price changed, item unavailable, restaurant closed).
- An explicit **consistency story**: where the system is eventually consistent vs. the single strong-consistency gate, and *why*.
- **Concurrency handling**: the multi-device first-create race, lost-update prevention, and idempotent retries.
- **Pricing strategy**: estimate vs. authoritative re-price, modifier math, and never trusting client-sent prices.
- A thorough **checkout-validation sequence** and what happens on each failure.
- **Edge-case handling** for every item the prompt lists, plus scaling, reliability, failure modes, and observability.
### Follow-up Questions
- How would you extend the design to support **group ordering** (multiple users contributing to one basket for one restaurant)?
- If an item truly has limited stock, where and how would you **reserve inventory**, and what are the tradeoffs versus the current read-time-validation approach?
- How does your **abandoned-cart re-engagement** signal change if the durable store's TTL expiry emits no event (e.g. Cassandra tombstones vs. DynamoDB Streams)?
- How would you support **offline cart edits** on a mobile client and reconcile them when connectivity returns?
Quick Answer: This question evaluates a candidate's ability to design a distributed shopping-cart service for a food-delivery platform, testing competencies in system architecture, data modeling, API design, consistency models, concurrency control, scalability, reliability, and failure handling.