A comprehensive guide to building a large-scale online shopping platform like Amazon — covering product catalog, shopping cart, inventory management, order processing, and handling massive traffic during flash sales.
This section provides a high-level overview of how a purchase flows through the system.
Key Insight: The core challenge is maintaining inventory consistency under extreme concurrency while providing sub-second response times during traffic spikes.
Before designing the solution, we must understand what an e-commerce platform needs to accomplish and the constraints it operates under.
An e-commerce platform connects millions of buyers with hundreds of millions of products from thousands of sellers. The system must handle browsing, searching, carting, checkout, payment, and fulfillment — all while maintaining data consistency and delivering exceptional performance even during peak sale events.
20M orders / 86,400s ≈ 230 orders/second
230 × 100 (Prime Day) ≈ 23,000 orders/second
5B / 86,400s ≈ 58,000 requests/second
350M products × 10KB avg ≈ 3.5 TB catalog data
Key Challenge: The system is both read-heavy (browsing) and write-heavy (orders) during peaks. Inventory updates require strong consistency while product reads can be eventually consistent.
The platform consists of multiple microservices, each handling specific business domains.
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ Mobile/ │────▶│ API │────▶│ Product │
│ Web App │◀────│ Gateway │◀────│ Service │
└─────────────┘ └──────────────┘ └────────┬────────┘
│ │
┌─────────────────────┼──────────────────────┼──────────┐
│ │ │ │
┌─────▼─────┐ ┌──────────▼──────┐ ┌─────────▼───┐ │
│ Search │ │ Cart │ │ Inventory │ │
│ Service │ │ Service │ │ Service │ │
└─────┬─────┘ └────────┬────────┘ └──────┬──────┘ │
│ │ │ │
│ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │ Order │ │ Payment │ │
│ │ Service │───────│ Service │ │
│ └──────┬──────┘ └─────────────┘ │
│ │ │
┌─────▼─────┐ ┌──────▼──────┐ ┌───────────▼───┐
│Elasticsearch│ │ Fulfillment │ │ Notification │
│ Cluster │ │ Service │ │ Service │
└────────────┘ └─────────────┘ └───────────────┘Manages product catalog, handles search queries with faceted filtering. Uses Elasticsearch for fast full-text search across 350M+ products.
Manages shopping carts with low-latency reads/writes. Stores cart data in Redis for logged-in users and handles cart merging on login.
Tracks stock levels across warehouses. Implements reservation system during checkout to prevent overselling with strong consistency guarantees.
Orchestrates the order lifecycle from creation through delivery. Coordinates with warehouses, shipping carriers, and tracking systems.
With 350M+ products, efficient search and filtering is critical. Users expect instant results with sophisticated filtering options.
Product {
product_id: UUID
seller_id: UUID
title: VARCHAR(500)
description: TEXT
category_path: VARCHAR[] // ["Electronics", "Phones", "Smartphones"]
brand: VARCHAR(100)
price: DECIMAL
currency: VARCHAR(3)
images: VARCHAR[] // CDN URLs
attributes: JSONB // {"color": "black", "storage": "128GB"}
rating: DECIMAL(2,1)
review_count: INT
created_at: TIMESTAMP
updated_at: TIMESTAMP
}Primary search engine for product discovery.
1. User types "wireless headphones"
2. Query processor adds synonyms, fixes typos
3. Elasticsearch returns matching products
4. Apply user filters (brand, price range)
5. Boost by conversion rate, reviews, Prime
6. Return paginated results with facet counts
// Elasticsearch Query for "wireless headphones" with filters
{
"query": {
"bool": {
"must": [
{ "multi_match": { "query": "wireless headphones", "fields": ["title^3", "description"] }}
],
"filter": [
{ "term": { "category": "Electronics" }},
{ "range": { "price": { "gte": 50, "lte": 200 }}},
{ "range": { "rating": { "gte": 4.0 }}}
]
}
},
"aggs": {
"brands": { "terms": { "field": "brand" }},
"price_ranges": { "histogram": { "field": "price", "interval": 50 }}
},
"sort": [
{ "_score": "desc" },
{ "conversion_rate": "desc" }
]
}The shopping cart is a high-traffic, low-latency component. Users expect instant updates when adding or removing items.
Cart stored in Redis with user_id as key. Persists across sessions and devices.
Key: cart:{user_id}
TTL: 30 days
Backup: Async write to DynamoDB
Cart stored with session_id. Merged into account on login/signup.
Key: cart:guest:{session_id}
TTL: 7 days
Cookie tracks session
Cart {
cart_id: UUID
user_id: UUID (nullable for guests)
session_id: VARCHAR (for guests)
items: [
{
product_id: UUID,
seller_id: UUID,
quantity: INT,
price_snapshot: DECIMAL, // Price when added
added_at: TIMESTAMP
}
],
updated_at: TIMESTAMP
}
// Redis Hash Structure
HSET cart:user123 product_abc '{"qty":2,"price":29.99,"added":"2025-01-15"}'
HSET cart:user123 product_xyz '{"qty":1,"price":149.99,"added":"2025-01-15"}'When a guest user logs in, their guest cart merges with their existing account cart:
Fetch guest cart by session_id
Fetch existing user cart by user_id
Merge items: sum quantities for duplicates, add new items
Update prices to current values (notify if changed)
Delete guest cart, persist merged cart
Inventory consistency is critical. Overselling damages customer trust and creates operational nightmares. The system must handle thousands of concurrent purchases for the same item.
Inventory {
product_id: UUID
warehouse_id: UUID
total_quantity: INT // Physical stock
reserved: INT // Held during checkout
available: INT // total - reserved (computed)
version: INT // For optimistic locking
updated_at: TIMESTAMP
}
// Constraint: available = total_quantity - reserved >= 01. User clicks "Proceed to Checkout"
2. Inventory service reserves quantities
3. User has 15 minutes to complete payment
4. Payment success → Convert reservation to sale
5. Payment fail/timeout → Release reservation
• TTL-based expiration in Redis
• Background job releases stale reservations
• Idempotent release operations
• Audit log for debugging
Lock inventory row before checking/updating. Guarantees consistency but limits throughput.
SELECT * FROM inventory
WHERE product_id = ?
FOR UPDATE;
✓ Strong consistency guaranteed
✗ High contention during flash sales
Check version on update, retry on conflict. Better throughput with retry overhead.
UPDATE inventory SET
reserved = reserved + 1,
version = version + 1
WHERE product_id = ?
AND version = ? AND available > 0;
✓ Better concurrency
~ Requires retry logic
Recommended Approach: Use Redis with Lua scripts for atomic reservation operations. Lua scripts execute atomically, providing both consistency and high throughput. Fall back to database for durability.
Order creation is a distributed transaction spanning inventory, payment, and order services. Failures at any step must be handled gracefully.
┌──────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐
│ CREATED │───▶│ PAYMENT │───▶│ CONFIRMED │───▶│ SHIPPED │
└──────────┘ │ PENDING │ └───────────┘ └───────────┘
└─────┬─────┘ │ │
│ │ ▼
▼ │ ┌───────────┐
┌───────────┐ │ │ DELIVERED │
│ PAYMENT │ │ └───────────┘
│ FAILED │ │
└───────────┘ ▼
┌───────────┐
│ CANCELLED │
└───────────┘Use the Saga pattern for distributed transactions with compensating actions:
Reserve Inventory
Decrement available, increment reserved for each item
Compensate: Release reservation
Create Order Record
Persist order with PAYMENT_PENDING status
Compensate: Mark order as CANCELLED
Process Payment
Charge customer via payment gateway
Compensate: Refund payment
Confirm Order
Convert reservation to sale, update order status
Send confirmation email, trigger fulfillment
Order {
order_id: UUID
user_id: UUID
status: enum
shipping_address: JSONB
billing_address: JSONB
items: [{
product_id: UUID,
seller_id: UUID,
quantity: INT,
unit_price: DECIMAL,
subtotal: DECIMAL
}],
subtotal: DECIMAL
tax: DECIMAL
shipping_cost: DECIMAL
total: DECIMAL
payment_id: UUID
created_at: TIMESTAMP
updated_at: TIMESTAMP
}Prime Day and Black Friday bring 100x traffic spikes. Flash sales have thousands competing for limited inventory in seconds.
Millions hit "Buy Now" at exactly 12:00:00, overwhelming databases.
Single popular product becomes a bottleneck as all requests hit one database row.
Concurrent checkouts for last item can oversell without proper locking.
Instead of letting everyone hit the buy button, place users in a queue. Process purchases sequentially from the queue.
For 1000 items, create 1000 tokens in Redis. Users atomically claim a token before proceeding.
Accept order intent immediately, process actual order asynchronously. Show "Order received, confirming..."
Cache product pages at edge. Only the "Buy" action hits origin servers.
Payment must be reliable, secure, and support multiple methods. Idempotency prevents double charges.
1. Create payment intent with order details
2. Generate idempotency key from order_id
3. Authorize payment (hold funds)
4. On order confirmation, capture payment
5. On cancellation, release authorization
6. Store payment record with gateway reference
Prevent double charges from retries or network issues:
Idempotency-Key: order_{order_id}
// Store in Redis with 24h TTL
// Return cached result on duplicate
Payment {
payment_id: UUID
order_id: UUID
user_id: UUID
amount: DECIMAL
currency: VARCHAR(3)
method: enum (card, wallet, bank_transfer)
status: enum (pending, authorized, captured, failed, refunded)
gateway: VARCHAR (stripe, paypal, etc.)
gateway_ref: VARCHAR
idempotency_key: VARCHAR (unique)
created_at: TIMESTAMP
captured_at: TIMESTAMP
}Partition data to handle massive scale:
Products DB: Shard by category_id → Electronics, Books, Fashion on separate shards → Each shard handles ~50M products Orders DB: Shard by user_id → User's orders always on same shard → Range-based sharding for even distribution Inventory DB: Shard by product_id → Co-locate with product data → Hot products may need dedicated shards
Deploy infrastructure close to users:
Static assets, user preferences. TTL: hours to days.
Product pages, images. TTL: minutes. Purge on update.
Session, cart, inventory counts. TTL: seconds to minutes.
Design an e-commerce platform with an AI interviewer and receive instant feedback on your approach.