Requirements & scope
Problem Statement & Requirements
Design a large-scale e-commerce platform that allows sellers to list products, buyers to browse/search/purchase them, and the platform to handle the entire order lifecycle from cart to delivery — similar to Amazon, Shopify, or eBay.
Functional Requirements
- Product Catalog — sellers create, update, and manage product listings with images, descriptions, variants (size/color), and pricing
- Search & Browse — full-text search, category navigation, filters (price, rating, brand), sorting (relevance, price, newest)
- Shopping Cart — add/remove items, persist across sessions, handle inventory changes (item goes out of stock while in cart)
- Checkout & Order — address selection, shipping method, payment, order placement (atomic: reserve inventory + charge + create order)
- Inventory Management — real-time stock tracking per SKU per warehouse; prevent overselling
- Order Management — order status tracking (placed → paid → shipped → delivered → returned)
- Reviews & Ratings — customers rate and review purchased products
- Recommendations — "Customers who bought X also bought Y", personalized homepage
- Seller Dashboard — order management, inventory, analytics, payouts
- Promotions & Coupons — percentage/fixed discounts, flash sales, buy-one-get-one
Non-Functional Requirements
- High availability — 99.99% (< 53 min downtime/year); checkout must never go down
- Low latency — product page load < 200 ms; search results < 100 ms; checkout < 2 seconds
- Massive scale — 500M products, 300M active buyers, 2M sellers
- Consistency for inventory — never oversell; stock count must be accurate
- Eventual consistency acceptable — for reviews, ratings, recommendations
- Handle traffic spikes — 10x normal during sales events (Prime Day, Black Friday)
- Global reach — serve users across multiple continents with low latency
Out of Scope
- Warehouse robotics / physical logistics
- Advertising auction system (sponsored products)
- Detailed payment processing internals (see Payment System design)
- Customer support / ticketing system
Scale estimations
Scale Estimations
Traffic
| Metric | Value |
|---|---|
| Daily active buyers | 100M |
| Product page views / day | 5B |
| Search queries / day | 1B |
| Product page views / second | ~58K RPS |
| Search queries / second | ~12K RPS |
| Add to cart / day | 500M |
| Orders placed / day | 50M |
| Orders / second (avg) | ~580 TPS |
| Orders / second (peak — Black Friday) | ~6,000 TPS |
| Peak total RPS (all endpoints) | ~500K RPS |
Storage
| Metric | Value |
|---|---|
| Total products (active listings) | 500M |
| Average product record | 10 KB (text metadata, variants, pricing) |
| Product catalog storage | 500M × 10 KB = ~5 TB |
| Product images | 500M × 8 images × 500 KB = ~2 PB (in object storage) |
| Orders per year | 50M/day × 365 = ~18B |
| Order record size | 2 KB |
| Order storage per year | 18B × 2 KB = ~36 TB |
| Reviews | 5B total × 500 bytes = ~2.5 TB |
| User profiles | 300M × 2 KB = ~600 GB |
| Search index | ~2 TB (inverted index for 500M products) |
Bandwidth
| Metric | Value |
|---|---|
| Product page responses (58K RPS × 50 KB avg incl images) | ~2.9 GB/s |
| Search responses (12K RPS × 5 KB) | ~60 MB/s |
| Image CDN egress | ~20 GB/s (hot images from CDN cache) |
| API total bandwidth | ~25 GB/s |
Hardware Estimate
| Component | Spec |
|---|---|
| Product Service | 30-50 instances |
| Search cluster (Elasticsearch) | 100-200 nodes (500M docs, 2 TB index) |
| Order Service | 20-50 instances |
| Inventory Service | 10-20 instances (hot path, heavily cached) |
| Cart Service | 10-20 instances (Redis-backed) |
| Primary database | 50-100 shards (PostgreSQL / MySQL) |
| Cache (Redis) | 50-100 nodes (product cache, session, cart) |
| CDN | 200+ PoPs (product images, static assets) |
Layered architecture
Phase 1 of 4 · Client & edge
Start with the entry points
First, define who uses the system and where requests enter. This is the boundary of the design, not yet a complete request path.
- Buyer
- Treat discovery and checkout as separate flows with different consistency requirements.
- API gateway
- Route browse, cart, and checkout operations to services with independent capacity.
This first layer defines the system boundary. The next chapters add application logic and data dependencies. After examining the request paths and tradeoffs, we will add operational safeguards and bring the complete architecture together.
API & contracts
Phase 2 of 4 · Application & compute
Add the application logic
Keep the entry points and add the services that do the work. Give each service a clear responsibility before defining its contracts. Storage and background dependencies come next.
- Catalog + search
- Publish catalog changes to a derived search index; tolerate bounded discovery staleness.
- Order service
- Coordinate inventory reservation, payment, and order confirmation with compensating actions.
API Design
Product Catalog
GET /api/v1/products/{product_id}
Response (200 OK):
{
"product_id": "prod-abc123",
"title": "Wireless Bluetooth Headphones",
"description": "Active noise cancelling, 30hr battery...",
"brand": "SoundMax",
"category": ["Electronics", "Audio", "Headphones"],
"seller_id": "seller-xyz",
"base_price": 7999, // cents
"currency": "usd",
"variants": [
{
"sku": "SKU-BLK-001",
"attributes": {"color": "Black"},
"price": 7999,
"inventory": {"in_stock": true, "quantity": 234}
},
{
"sku": "SKU-WHT-002",
"attributes": {"color": "White"},
"price": 8499,
"inventory": {"in_stock": true, "quantity": 12}
}
],
"images": [
{"url": "https://cdn.example.com/prod-abc123/main.jpg", "position": 1},
{"url": "https://cdn.example.com/prod-abc123/side.jpg", "position": 2}
],
"rating": {"average": 4.3, "count": 1847},
"shipping": {"free_shipping": true, "estimated_days": "2-4"},
"created_at": "2025-06-15T10:00:00Z"
}Search
GET /api/v1/search?q=wireless+headphones
&category=Electronics
&price_min=3000&price_max=10000
&rating_min=4
&sort=relevance
&page=1&per_page=24
Response (200 OK):
{
"query": "wireless headphones",
"total_results": 4523,
"page": 1,
"results": [
{
"product_id": "prod-abc123",
"title": "Wireless Bluetooth Headphones",
"price": 7999,
"rating": 4.3,
"review_count": 1847,
"image_url": "https://cdn.example.com/.../thumb.jpg",
"is_prime": true,
"relevance_score": 0.94
},
...
],
"facets": {
"brand": [{"name": "SoundMax", "count": 120}, {"name": "BeatPro", "count": 89}],
"price_range": [{"range": "0-5000", "count": 1200}, {"range": "5000-10000", "count": 890}],
"rating": [{"stars": 4, "count": 3100}, {"stars": 3, "count": 1423}]
},
"did_you_mean": null
}Cart
POST /api/v1/cart/items
{
"sku": "SKU-BLK-001",
"quantity": 2
}
GET /api/v1/cart
Response:
{
"cart_id": "cart-user123",
"items": [
{
"sku": "SKU-BLK-001",
"product_id": "prod-abc123",
"title": "Wireless Bluetooth Headphones (Black)",
"quantity": 2,
"unit_price": 7999,
"subtotal": 15998,
"in_stock": true,
"reserved_until": null // stock not reserved until checkout
}
],
"subtotal": 15998,
"estimated_tax": 1440,
"estimated_shipping": 0,
"estimated_total": 17438
}Checkout & Place Order
POST /api/v1/checkout
Idempotency-Key: checkout-ord-456
Request:
{
"cart_id": "cart-user123",
"shipping_address_id": "addr-home",
"shipping_method": "standard",
"payment_method_id": "pm_card_4242",
"coupon_code": "SAVE10"
}
Response (201 Created):
{
"order_id": "ord-789xyz",
"status": "confirmed",
"items": [...],
"subtotal": 15998,
"discount": -1600, // SAVE10 = 10%
"tax": 1296,
"shipping": 0,
"total": 15694,
"payment_intent_id": "pi_abc123",
"estimated_delivery": "2026-04-07",
"created_at": "2026-04-03T10:30:00Z"
}Order Status
GET /api/v1/orders/{order_id}
Response:
{
"order_id": "ord-789xyz",
"status": "shipped",
"tracking": {
"carrier": "UPS",
"tracking_number": "1Z999AA10123456784",
"estimated_delivery": "2026-04-07",
"current_location": "Distribution Center, Memphis TN"
},
"timeline": [
{"status": "confirmed", "at": "2026-04-03T10:30:00Z"},
{"status": "paid", "at": "2026-04-03T10:30:02Z"},
{"status": "processing", "at": "2026-04-03T11:00:00Z"},
{"status": "shipped", "at": "2026-04-04T08:15:00Z"}
]
}Data model
Phase 3 of 4 · Data & async work
Connect data and background work
The services now need their dependencies: durable state, fast lookups, or work that continues outside a request. Separate these responsibilities rather than treating every component as a database.
- Cart store
- Keep fast mutable cart state without treating a displayed price as a guaranteed checkout price.
- Inventory database
- Atomically reserve stock and expire abandoned reservations to prevent overselling.
- Order database
- Persist the order state machine and unique checkout identity before asynchronous follow-up.
Data Model
Product & Variants
Order
Cart (Redis)
Core design decisions
Core Design Decisions
Decision 1: Checkout Flow — Preventing Overselling
This is THE hardest problem in e-commerce. Two users checkout the last item simultaneously.
Option A: Pessimistic Locking (SELECT FOR UPDATE)
| Pros | Cons |
|---|---|
| Simple, correct, no race condition | Lock contention on hot SKUs (flash sales!) |
| Database guarantees consistency | Throughput limited by lock hold time |
| Works with any SQL database | Can deadlock if multi-row updates |
Option B: Optimistic Locking (CAS with Version)
| Pros | Cons |
|---|---|
| No locks held → higher concurrency | Retry storms under extreme contention |
| Better throughput for most-not-contended SKUs | More complex client logic (retry loop) |
| No deadlocks possible | Starvation possible (always retrying, never winning) |
Option C: Redis Atomic Decrement (for Hot Items)
| Pros | Cons |
|---|---|
| Extremely fast (100K+ ops/sec per key) | Redis is not the source of truth (must sync to DB) |
| Zero contention (atomic operation) | Data loss risk if Redis crashes before sync |
| Perfect for flash sales / hot items | Extra infrastructure complexity |
Recommendation: Hybrid
Normal products: Optimistic locking in PostgreSQL (Option B)
→ Sufficient for 99% of SKUs (low contention)
→ Simple, DB is source of truth
Hot items / flash sales: Redis atomic decrement (Option C)
→ Pre-load stock count before sale starts
→ DECRBY for reservations, sync to DB async
→ Fall back to DB if Redis unavailableDecision 2: Search Architecture
Decision 3: Microservice Boundaries
Request flows
Detailed Flow Diagrams
Checkout Flow (The Most Critical Path)
Checkout Failure Compensation (Saga Pattern)
Product Page Load Flow
Performance & caching
Caching Strategy
Advanced design
Inventory Management Deep Dive
Multi-Warehouse Inventory
Inventory Reservation Lifecycle
Event-Driven Communication Between Services
Edge cases
Handling Edge Cases
Flash Sale Thundering Herd
Problem: 10M users hit "Buy" at 12:00:00 for 1,000 units of a hot item
Solution: Multi-layer defense
Layer 1: Rate limiting at API gateway
→ Max 1 checkout request per user per 5 seconds
→ Eliminates bot rapid-fire
Layer 2: Virtual queue
→ At 11:59, users enter a virtual queue (random position)
→ Release users in batches of 1,000 every second
→ Queue page shows estimated wait time
→ Prevents 10M simultaneous DB writes
Layer 3: Redis atomic decrement for stock
→ Pre-load 1,000 into Redis: SET stock:SKU-HOT 1000
→ DECRBY stock:SKU-HOT 1 (atomic, 100K+ ops/sec)
→ First 1,000 proceed; rest see "sold out" instantly
→ No DB contention at all for the "sold out" path
Layer 4: Async order creation
→ The 1,000 winners get reservation tokens
→ Have 10 minutes to complete checkout
→ Actual order processing happens async (not in the thundering herd)Price Changed During Checkout
Problem: Buyer adds item at $79.99, price changes to $89.99 during checkout
Solution: Price snapshot at cart add + revalidation at checkout
1. Cart stores price_at_add: $79.99
2. At checkout, re-fetch current price: $89.99
3. Compare: different!
4. Options:
a) HONOR cart price (Amazon approach — better UX)
→ Show buyer: "Price was $89.99, you're getting it for $79.99"
b) UPDATE to current price
→ Show buyer: "Price changed to $89.99 since you added to cart"
→ Let buyer decide to proceed or remove
Recommendation: Honor cart price for small increases (< 10%)
Alert buyer for large increases (> 10%)Distributed Order Across Multiple Sellers
Abandoned Cart Recovery
Cart abandoned (user added items but didn't checkout)
Trigger: Cart has items AND no checkout in 1 hour
Recovery pipeline:
T+1h: Email "You left items in your cart!" (with product images)
T+24h: Push notification "Your cart is waiting"
T+72h: Email with 10% discount code "Complete your purchase"
T+7d: Final email "Items in your cart are going fast"
T+30d: Cart auto-expires (Redis TTL)
Conversion rate from abandoned cart emails: ~5-10%
At 500M carts/day, even 5% = 25M recovered ordersTradeoffs
Tradeoffs & Design Decisions Summary
| Decision | Option A | Option B | Chosen | Why |
|---|---|---|---|---|
| Inventory locking | Pessimistic (SELECT FOR UPDATE) | Optimistic (CAS version) | Hybrid: optimistic + Redis for hot items | Optimistic handles 99% of SKUs; Redis for flash sales |
| Cart storage | SQL database | Redis | Redis | Temporary data, high-churn, sub-ms access, auto-expiry |
| Search | SQL LIKE queries | Elasticsearch | Elasticsearch | Full-text, faceted search, relevance scoring at 12K QPS |
| Search sync | Dual-write (app → DB + ES) | CDC pipeline (DB → Kafka → ES) | CDC | No dual-write consistency issues; decoupled; DB is source of truth |
| Checkout | Synchronous all-in-one | Saga (orchestrated) | Saga | Multi-service coordination; compensating actions on failure |
| Product images | Stored in DB | Object storage + CDN | S3 + CDN | 2 PB of images can't live in DB; CDN for global low-latency delivery |
| Pricing | Static (in product table) | Dynamic pricing service | Dedicated service | Promotions, coupons, flash sales, A/B testing require decoupled pricing |
| Order data | Current price from product | Snapshot at order time | Snapshot | Product can change; order must reflect what buyer actually purchased |
| Architecture | Monolith | Microservices | Microservices | Different services have vastly different scaling/consistency needs |
| Consistency | Strong everywhere | Mixed: strong for orders/inventory, eventual for catalog/search | Mixed | Strong where money/stock is involved; eventual acceptable for reads |
Reliability & fault tolerance
Phase 4 of 4 · Operations & resilience
Add operational safeguards
With the request paths and tradeoffs established, add the controls that help detect trouble and keep the system operating. The final diagram retains every layer introduced so far.
- Event bus
- Publish committed changes reliably and let search, notifications, and recommendations update independently.
- Payments
- Use stable payment identities and compensate reservations if payment definitively fails.
Reliability & Fault Tolerance
Single Points of Failure & Mitigations
Graceful Degradation
Tier 1 (non-critical service down — Reviews, Recommendations):
→ Product page still loads, just without reviews/recs section
→ "Reviews temporarily unavailable" placeholder
→ Zero impact on checkout flow
Tier 2 (Search down):
→ Category browsing still works (served from cache/DB)
→ Search bar shows "Search is temporarily unavailable"
→ Redirect to category pages and "popular products"
→ Checkout unaffected
Tier 3 (Cart Redis down):
→ Fall back to session-cookie cart (limited, smaller)
→ Or: serve from DB-backed cart (slower, 50ms vs 1ms)
→ Checkout still functional
Tier 4 (Inventory Service degraded):
→ Accept orders with delayed inventory check
→ Queue orders; process when service recovers
→ Risk: small chance of overselling (notify buyer if so)
→ Better than blocking all orders during outage
Tier 5 (Payment Service down):
→ Checkout blocked (can't charge without payment)
→ Show: "Checkout temporarily unavailable, please retry"
→ Cart preserved, reserved inventory held
→ This is the one service where we CANNOT degradeProduction architecture
High-Level Architecture
Component Breakdown (Service Map)
Full System Architecture (Production-Grade)
Further exploration
Run a flash sale for one product while the rest of the catalog receives ordinary traffic. Protect the hot inventory key without slowing every product page. Then cancel a paid order after stock has been reserved: describe the separate inventory, payment, and order transitions instead of treating cancellation as deleting a row.
Interview playbook
Interview Tips
Start with the checkout flow — This is the core of the system and the hardest part. Draw the saga: validate cart → reserve inventory → charge payment → create order. Explain what happens when each step fails (compensating actions).
Inventory overselling is the #1 follow-up — Have three solutions ready: pessimistic locking (simple, slow), optimistic locking (better throughput), Redis atomic decrement (flash sales). Explain when each applies.
Separate read and write paths — Product views (58K RPS, eventual consistency) vs checkout (580 TPS, strong consistency) are fundamentally different. Show you understand this by designing different solutions for each.
Search is a separate system, not a database query — Don't say "SELECT ... LIKE '%headphones%'". Explain: CDC pipeline → Kafka → Elasticsearch → faceted search with relevance scoring. 1-5 second index lag is acceptable.
Cart in Redis, not SQL — Explain why: temporary data, high-churn, sub-ms access, TTL for abandoned cart cleanup. 300M entries fit in ~100 GB Redis. Mention the fallback to DB-backed cart if Redis fails.
Price and title snapshot in order — Product can change after order is placed. The order MUST record what the buyer actually purchased: price, title, image URL — all snapshotted. Never join back to live product table for historical orders.
Flash sale architecture — Virtual queue → rate-limited admission → Redis stock counter → async order processing. This shows you can handle 10x traffic spikes without designing the entire system for peak.
Multi-seller, multi-warehouse — One order can involve 3 sellers from 2 warehouses. Explain sub-orders / fulfillment groups: each seller fulfills independently with its own tracking number. Buyer sees unified view.
Event-driven for async work — OrderCreated → email, seller notification, analytics, recommendation update. Don't make these synchronous in the checkout path. Kafka event bus decouples services.
End with caching layers — CDN (images) → API gateway cache (product JSON, 60s) → Redis (product/session/cart) → L1 in-process cache (category tree). Mention what is NOT cached: inventory counts, order state, payment status.