Menu
Course/Real-World Case Studies/Design an E-Commerce Platform

Design an E-Commerce Platform

Product catalog, inventory management, shopping cart, checkout flow, payment processing, order fulfillment, and handling flash sales.

25 min readHigh interview weight

Problem Statement

An e-commerce platform enables buyers to browse products, add items to a cart, and complete purchases. The distinct challenges are: (1) a product catalog that must serve millions of queries per second with fast search, (2) inventory management that prevents overselling, and (3) flash sales that create extreme traffic spikes. The correctness requirement for payments and inventory makes this more demanding than a typical read-heavy system.

Requirements

FunctionalNon-Functional
Browse and search product catalog< 100 ms page load (P95)
Add/remove items from cartInventory must never go negative (no oversell)
Checkout: address, payment, order confirmation99.99% availability for checkout flow
Order history and status trackingHandle 100x traffic spikes during flash sales
Seller catalog management10 M products, 100 M DAU
Reviews and ratingsPayment processing with PCI DSS compliance

High-Level Architecture

Loading diagram...
E-commerce platform high-level architecture

Product Catalog

Product data is stored in MySQL (structured: SKU, price, seller, category) and indexed in Elasticsearch for full-text search with faceted filtering. Product pages are cached aggressively in Redis (TTL: 5 minutes) and at the CDN layer for static assets. The read:write ratio is typically 100:1 or higher — optimize relentlessly for reads.

sql
CREATE TABLE products (
  product_id  BIGINT PRIMARY KEY,
  seller_id   BIGINT NOT NULL,
  title       VARCHAR(500) NOT NULL,
  description TEXT,
  price_cents INT NOT NULL,       -- store money as integers (cents)
  category_id INT NOT NULL,
  status      ENUM('active','inactive','draft') DEFAULT 'active',
  created_at  TIMESTAMP DEFAULT NOW(),
  updated_at  TIMESTAMP DEFAULT NOW() ON UPDATE NOW()
);

CREATE TABLE inventory (
  product_id    BIGINT PRIMARY KEY,
  warehouse_id  INT NOT NULL,
  quantity      INT NOT NULL DEFAULT 0,
  reserved      INT NOT NULL DEFAULT 0,  -- items in active carts/checkouts
  CHECK (quantity >= 0),
  CHECK (reserved >= 0),
  CHECK (quantity >= reserved)
);

Shopping Cart

The cart is a temporary, user-specific data structure. Redis Hashes are ideal: `HSET cart:{userId} productId quantity`. Key design decisions:

  • Guest carts: use a cookie-based `sessionId` as the key; merge into user cart on login.
  • Cart TTL: expire guest carts after 7 days (`EXPIRE cart:{sessionId} 604800`).
  • No inventory reservation at cart time: only reserve when checkout begins to avoid holding inventory for abandoned carts.
  • Idempotent updates: use `HSET` (set) not `HINCRBY` (increment) for quantity to handle duplicate requests.

Inventory and Checkout — Preventing Oversell

Preventing overselling is the most critical correctness requirement. Three approaches exist:

ApproachMechanismConsistencyPerformance
Pessimistic lockingSELECT ... FOR UPDATE on inventory rowStrong — no race conditionsLow — locks serialize checkouts
Optimistic concurrency (CAS)UPDATE inventory SET qty = qty-N WHERE qty >= N AND version = VStrong — retry on conflictHigher — no locks held
Redis atomic decrementDECRBY quantity in Redis; DB synced asyncEventually consistentHighest — sub-ms ops

Recommended: use Redis `DECRBY` as a fast reservation gate. If Redis quantity >= requested amount, decrement atomically and proceed. If it fails, return 'out of stock' immediately without hitting the DB. Sync Redis inventory to MySQL asynchronously. For final DB commit, use optimistic concurrency to catch any rare discrepancies.

Checkout Flow

Loading diagram...
Checkout flow with inventory reservation and payment

Flash Sales

Flash sales (e.g., Black Friday, product launches) cause traffic spikes of 100x normal. Strategies to handle them:

  • Pre-register interest: use a waiting room / virtual queue page to absorb the spike. Issue time-stamped tokens; process in batches.
  • Redis inventory gate: pre-load the sale inventory count into Redis. Use Lua script for atomic check-and-decrement to prevent race conditions.
  • Rate limiting: apply aggressive per-user rate limits on the checkout endpoint during flash sales.
  • Pre-scale: provision extra capacity 30 minutes before the sale starts using auto-scaling or pre-warmed instances.
  • Static product pages: serve the product page from CDN — don't hit the origin for static content during peak.
📌

Atomic Inventory Decrement with Lua

Redis Lua scripts run atomically. A script that checks quantity >= requested and decrements if so prevents race conditions without explicit locks, even under 100K concurrent requests.

lua
-- Redis Lua script for atomic inventory reservation
local key = KEYS[1]           -- e.g., "inventory:product:42"
local requested = tonumber(ARGV[1])
local current = tonumber(redis.call("GET", key) or "0")

if current >= requested then
  redis.call("DECRBY", key, requested)
  return 1  -- success
else
  return 0  -- out of stock
end
💡

Interview Tip

The inventory oversell problem is the core technical challenge in e-commerce system design. Explain all three approaches (pessimistic lock, optimistic CAS, Redis atomic) and justify why Redis + atomic Lua is best for flash sales. Interviewers also look for awareness of the 2-phase commit problem: what happens if payment succeeds but inventory commit fails? The answer is idempotency keys and a compensating transaction (refund).

📝

Knowledge Check

5 questions

Test your understanding of this lesson. Score 70% or higher to complete.

Ask about this lesson

Ask anything about Design an E-Commerce Platform