Design a Flash Sale System (High Concurrency Checkout)
Design a Flash Sale System (High Concurrency Checkout)
Flash sales—such as limited sneaker drops, Black Friday PlayStation launches, or Taylor Swift concert tickets—present one of the most brutal engineering challenges in distributed systems: millions of concurrent users slamming the platform to buy only 1,000 available items within the span of 30 seconds.
1. System Requirements
Functional Requirements
- Flash Sale Landing Page: Display item details, current price, countdown timer, and live inventory state (
IN_STOCK,FEW_LEFT,SOLD_OUT). - Virtual Waiting Room: When incoming traffic surpasses backend capacity, queue users fairly in a virtual waiting room with an estimated wait time.
- Atomic Inventory Reservation: Reserve an item for 10 minutes upon successful checkout entry. If the user completes payment within 10 minutes, the order is confirmed; otherwise, inventory releases back to the pool.
- Order Placement & Idempotent Payment: Securely finalize checkout with payment gateway integrations without double charges.
- Anti-Bot & Abuse Prevention: Block scripted automated bot scalpers using CAPTCHAs, device fingerprinting, and account velocity checks.
Non-Functional Requirements
- Strict Zero Overselling: 1,000 available items must result in *at most* 1,000 confirmed sales. Overbooking is catastrophic.
- Database Protection: The relational database must never be exposed to millions of concurrent read/write requests; traffic must be absorbed at the edge and memory tier.
- High Availability: 99.99% uptime during the 30-minute flash sale window.
- Fairness: Prevent early request leaks and ensure fair FIFO or lottery-based admission from the virtual waiting room.
2. Capacity & Scale Estimation
- Total Inventory: 5,000 units.
- Registered Shoppers: 2,000,000 users.
- Traffic Surge at Drop (T=0): 500,000 concurrent active users clicking "Buy Now" within the first 5 seconds $\rightarrow 100,000\text{ peak QPS}$.
- Database Master Capacity: Standard PostgreSQL master handles ~2,000 write transactions/sec.
- Core Problem: $100,000\text{ write QPS} \gg 2,000\text{ DB write capacity}$. The system will experience catastrophic database thread pool exhaustion without front-line shielding.
3. High-Level Architecture Blueprint
+-----------------------+
| Shopper Clients |
+-----------+-----------+
|
v
+-----------------------+
| Cloudflare CDN Edge |
| (Static Assets Cache) |
+-----------+-----------+
|
v
+-----------------------+
| Virtual Waiting Room |
| (Token Bucket / FIFO) |
+-----------+-----------+
| Admitted Shoppers (10k QPS)
v
+-----------------------+
| Flash Sale Gateway |
+-----------+-----------+
|
v
+-----------------------+
| Redis Cluster Memory |
| (Atomic Lua Script |
| Inventory Reservation)|
+-----+-----------+-----+
| |
+--------------------------+ +--------------------------+
| (Reserved Success) | (Stock Depleted)
v v
+------------------------+ +------------------------+
| Kafka Order Queue | | Return Immediate |
| (Buffered Writes) | | "Sold Out" Payload |
+-----------+------------+ +------------------------+
|
v
+------------------------+
| Order Execution Svc |
| (RDBMS Transaction) |
+-----------+------------+
|
v
+------------------------+
| Payment Gateway (PSP) |
+------------------------+4. Deep Dives & Core Engineering Patterns
Deep Dive 1: The Virtual Waiting Room
Before shoppers hit application servers, they encounter an edge Virtual Waiting Room:
- At $T-15\text{ minutes}$, arriving visitors receive a cryptographically signed cookie containing an assigned queue ticket number.
- The waiting room uses WebSockets or periodic polling (every 5s) to check queue progression.
- At drop time, the admission engine admits users in batches (e.g. 2,000 users per second) matching backend processing capacity.
- Admitted users receive a temporary JWT checkout token valid for 10 minutes.
Deep Dive 2: Atomic Inventory Reservation with Redis Lua
Relational row locks (SELECT ... FOR UPDATE) cause deadlocks under 100,000 concurrent updates. Instead, inventory is pre-warmed in Redis and reserved atomically via Lua:
-- KEYS[1]: flash_sale:{item_id}:stock
-- KEYS[2]: flash_sale:{item_id}:reservations
-- ARGV[1]: user_id
-- ARGV[2]: quantity (e.g., 1)
-- ARGV[3]: reservation_ttl_seconds (e.g., 600)
local stock = tonumber(redis.call('get', KEYS[1]) or '0')
if stock < tonumber(ARGV[2]) then
return -1 -- SOLD_OUT
end
-- Check if user already has an active reservation
if redis.call('hexists', KEYS[2], ARGV[1]) == 1 then
return -2 -- ALREADY_RESERVED
end
-- Atomically decrement stock and record user reservation
redis.call('decrby', KEYS[1], ARGV[2])
redis.call('hset', KEYS[2], ARGV[1], ARGV[3])
return 1 -- SUCCESSBecause Redis executes Lua scripts as a single atomic, uninterruptible operation on its event loop, race conditions are mathematically impossible.
Deep Dive 3: Inventory Release on Payment Expiration
If a user reserves an item but abandons checkout:
- The reservation carries a 10-minute TTL.
- When the timer expires, a Redis KeySpace notification or a delayed Kafka message triggers a compensation worker that increments the Redis inventory counter:
INCRBY flash_sale:{item_id}:stock 1.
Key Architecture Trade-Offs & Decision Matrix
| Decision Factor | Choice A | Choice B | Selected Architectural Rationale |
|---|---|---|---|
| Communication Protocol | REST over HTTP/2 | WebSockets / gRPC | Use REST for stateless CRUD APIs; use WebSockets for low-latency bidirectional streaming. |
| State Management | Centralized Distributed Store | Local Memory with Sticky Sessions | Centralized Redis / Database state allows seamless container auto-scaling and zero-downtime rolling deploys. |
| Concurrency Control | Optimistic Locking (version column) | Pessimistic Locking (SELECT FOR UPDATE) | Optimistic locking delivers superior throughput for low-conflict consumer operations. |
Related Topics
Expand your knowledge by learning about adjacent concepts in system design.
Design a URL Shortener (TinyURL / Bitly Architecture)
Design a scalable URL shortening service capable of handling billions of redirects: Base62 encoding, distributed ID generation, database indexing, and 301 vs 302 redirect trade-offs.
Design Bitly (Scalable URL Shortener & Analytics Platform)
Design a high-scale URL shortening and click tracking service like Bitly or TinyURL capable of handling billions of redirects with sub-15ms latency.
Dropbox
System design answer key for designing a file storage and synchronization service like Dropbox, built by FAANG managers and staff engineers.
Cheat Sheet Utility
View and print a concise system design reference card.