- Published on
- Views
Design E-commerce Cart, Order, and Inventory System Design Interview Guide
- Authors

- Name
- Javed Shaikh
← System Design Interview Preparation
This guide walks through Design E-commerce Cart, Order, and Inventory the way you would in a backend or Java interview. The numbers are interview estimates. They help you show your thinking. They are not a production capacity plan.
1. Problem
Shoppers browse products, fill a cart, check out, and expect the item they paid for to exist in a warehouse.
Example:
- Add a phone case, change quantity, remove a charger
- Checkout: reserve stock, create an order, take payment
- If payment fails, release the reservation
- If they abandon the cart, it expires
- Two people must not buy the last unit
This is the core of the longer e-commerce platform case study, focused on cart vs inventory races.
2. Functional Requirements / FR
| Requirement | What it means |
|---|---|
| Browse catalog | Product pages, price, availability hint. |
| Cart add / update / remove | Per user or guest cookie. |
| Checkout | Snapshot prices, shipping, totals. |
| Inventory reservation | Hold units for a few minutes. |
| Order creation | Durable order with line items. |
| Payment | Charge after (or during) reservation. |
| Stock deduction | Convert reservation to sold. |
| Cancel / refund | Restock if not shipped. |
| Cart expiry | Idle carts die; reservations die faster. |
Out of scope: full search ranking, ads, warehouse robotics, tax engines in depth.
3. Non-Functional Requirements / NFR
| Requirement | Why it matters |
|---|---|
| No oversell | Last-item races are the interview test. |
| Idempotent checkout | Double tap ≠ two orders. |
| Cart is eventually consistent | Fine if quantity UI lags a second. |
| Checkout is strongly consistent on stock | Reservation must be real. |
| Peak sale traffic | Flash sale QPS is bursty. |
| Guest + logged-in merge | Cart merge after login. |
Interview line: cart is a cache of intent. Inventory is the truth for stock. Order is the truth after pay.
4. Back-of-the-Envelope Calculation
Traffic assumptions
- 50 million DAU
- Average 20 product views / user / day (browse)
- 5% add to cart, 2% of DAU check out → 1 million checkouts/day
- Read/write: browse is read-heavy; checkout is write-critical
QPS
Browse:
50,000,000 × 20 = 1,000,000,000 views/day
1,000,000,000 / 86,400 ≈ 11,600 QPS
If peak is 5x, design for around 58,000 QPS (CDN + cache).
Checkout:
1,000,000 / 86,400 ≈ 12 QPS average
If peak is 5x, design for around 60 QPS of checkouts.
Flash sale: say 20x → around 240 QPS. Still about inventory, not CPU.
Cart updates might be 10× checkout (people fidget). Plan ~600 QPS cart writes at peak.
Storage
Cart JSON ≈ 2 KB, 10 million active carts → 20 GB.
Orders 1M/day × 2 KB ≈ 2 GB/day.
Inventory: millions of SKUs, small rows. Not the disk problem.
Cache / memory
Hot product pages in CDN/Redis. Stock counters for flash SKUs in Redis with DB as source.
Servers
Browse: many stateless boxes behind cache. Checkout: fewer, careful DB. Interview estimate: tens of catalog servers, a handful of order/inventory nodes, not exact production numbers.
5. APIs
GET /v1/products/{sku}
POST /v1/carts/{cartId}/items { sku, qty }
PATCH /v1/carts/{cartId}/items/{sku}
DELETE /v1/carts/{cartId}/items/{sku}
POST /v1/checkout
Idempotency-Key: <uuid>
{ "cartId", "addressId", "paymentMethodToken" }
GET /v1/orders/{orderId}
POST /v1/orders/{orderId}/cancel
Inventory is internal:
POST /internal/inventory/reservations { sku, qty, ownerId, ttlSeconds }
POST /internal/inventory/reservations/{id}/commit
POST /internal/inventory/reservations/{id}/release
Errors: 409 out of stock, 409 idempotency conflict, 410 cart expired.
6. Data Model
carts / cart_items
cart_id, user_id nullable, guest_id, updated_at, TTL. Items: sku, qty, price_hint.
products
Catalog: title, price, images. Availability is not only a boolean on this row at scale.
inventory
| Field | Notes |
|---|---|
sku | PK |
on_hand | Physical |
reserved | Held |
available | on_hand - reserved (or computed) |
version | Optimistic lock |
reservations
reservation_id, sku, qty, order_id nullable, expires_at, status (open, committed, released).
orders / order_lines
Snapshot name, sku, unit_price, qty. payment_id, status, idempotency_key.
Do not re-read catalog prices after the order exists.
7. High-Level Design
Checkout is a short workflow: reserve → pay → commit. Everything else is events.
E-commerce cart, order, and inventory architecture
Components:
- User → API Gateway → Cart Service
- Order Service on checkout
- Inventory Service + Inventory DB
- Payment Service
- Queue → Fulfillment Worker → Notification
Happy path:
- Browse cached catalog.
- Cart writes are cheap (Redis or DB).
- Checkout: create order
pending, reserve stock with TTL (e.g. 10 minutes). - Payment succeeds → commit reservation (reserved ↓, on_hand ↓) →
paid. - Event to fulfillment.
- Failure or expiry → release reservation.
Why reserve instead of decrement immediately? Payment can fail. You would hide stock from others forever.
8. Deep Dives
Cart expiry
Idle 7–30 days. Reservations are minutes, not days. Do not reserve on add-to-cart for a normal store (only for flash sales if product demands it).
Inventory race
Two checkouts, 1 unit:
UPDATE inventory SET reserved = reserved + 1 WHERE sku=? AND on_hand - reserved >= 1- Rows affected 0 →
409
Use a transaction or a single conditional update. Redis DECR alone is not enough unless Redis is the agreed source for that flash SKU and you persist later.
Payment
Call payment system with checkout idempotency key. If pay succeeds and commit fails, a worker commits or refunds. Never leave “paid but unreserved” silent.
Cancellation / refund
If not shipped: release remaining reservation or increment on_hand. If shipped: no restock without warehouse confirm.
Guest merge
On login, union carts. If both have the same sku, sum qty then clamp to available at checkout, not at merge.
Flash sale
Hot SKU: serialize with a queue per sku, or Redis stock + Lua check, plus a waiting room. Same idea as ticket locks.
9. Bottlenecks
- Hot SKU row in SQL
- Cart Redis memory on huge guest carts
- Payment latency inside checkout
- Oversell from cache-only stock on PDP (“3 left” is a hint, not a lock)
Mitigate: per-sku queues, cache for reads only, conditional writes for stock.
10. Tradeoffs
| Choice | Upside | Downside |
|---|---|---|
| Reserve on add-to-cart | Feels reserved | Lots of fake holds |
| Reserve on checkout | Honest stock | Last-second 409 |
| Soft oversell + cancel | Higher conversion | Angry customers |
| Single inventory DB | Simple correctness | Scale limits |
Pick: hint on PDP, reserve at checkout with TTL, conditional SQL/Redis, idempotent order.
11. Failure Modes
| Failure | Handling |
|---|---|
| Paid, reserve commit failed | Worker retries commit; else refund |
| Reservation TTL while user pays | Extend TTL on payment start, or fail checkout |
| Duplicate checkout | Same idempotency key |
| Inventory service down | Fail checkout, do not guess stock |
| Fulfillment worker down | Order stays paid; catch up from queue |
12. Interview Answer in 10 Minutes
"I would split browse, cart, inventory, and order.
Browse is 50 million users times 20 views: a billion reads a day, about 12,000 QPS, about 60,000 at 5× peak — CDN and cache. Checkout is 1 million a day, about 12 QPS, about 60 at peak. The design problem is the last item, not throughput.
Cart is short-lived intent. Checkout uses an idempotency key, snapshots prices, and reserves inventory with a TTL using a conditional update so two buyers cannot take the same unit. Then we pay. On success we commit the reservation and emit a fulfillment event. On failure or timeout we release.
Product page stock is a hint. The reservation is the lock."
13. Interview Talking Points
- Cart ≠ inventory.
- Conditional decrement / reservation.
- TTL holds.
- Idempotent checkout.
- Paid-but-failed-commit reconciliation.
- Metrics: oversell count (must be ~0), checkout 409 rate, reservation expiry rate, payment success.
- Classic Java services with Kafka after pay.
14. Follow-up Questions
SQL vs Redis for stock?
SQL for correctness at moderate QPS. Redis for flash SKUs with persistence and reconciliation.
Warehouse multi-location?
Reserve against a node or a pool; split inventory by warehouse_id.
Price change in cart?
Reprice at checkout. Cart prices are hints.
Spring?
Order saga or outbox: reservation, payment, commit. See event-driven Java tradeoffs.
15. Internal Links
Related JavaThoughts reading:
- System Design Interview Preparation
- Design a Payment System
- Design a Ticket Booking System
- Design Food Delivery / Order Workflow
- E-commerce platform system design
- Java
- Spring Boot
- Kafka
- Microservices
- Distributed Systems
- Event-driven architecture
- 20 system design concepts
Next in this series: Design a Ticket Booking System.
