System Design: High-Traffic Time-Deal Promotion System
CK 3788 Created at
17300
Step 1: Requirement Clarification
To design a resilient system capable of handling sudden traffic spikes during large-scale promotions, we define the following system requirements and boundaries:
1. User Scale & Traffic Patterns
Active Users: 10,000,000+ registered users.
Peak Traffic (The Spike): 1,000,000 Concurrent Users (CCU) at the exact second of the time-deal launch.
Peak QPS (Queries Per Second):
Read Traffic (Product/Deal Page): 200,000+ QPS.
Write Traffic (Order Placement): 50,000+ QPS.
Traffic Pattern: Sudden, extreme spike (step-function traffic) lasting for 1–5 minutes, followed by a rapid drop once stock is depleted.
2. Latency Requirements
Product/Promotion Browsing: $P_{99} < 100\text{ ms}$ (served via Edge/CDN).
Order Submission (Enqueueing): $P_{99} < 200\text{ ms}$ (immediate feedback of queue status).
Order Processing (Finalization): $P_{99} < 2\text{ seconds}$ (asynchronous processing via worker nodes).
3. Consistency vs. Availability Priorities (CAP Theorem)
Inventory (Stock Level): Consistency (CP) is the absolute priority. Zero overselling is allowed.
Promotion Discovery & Checkout Page: Availability (AP) is prioritized. If the transaction system is degraded, the user should see a graceful fallback (e.g., waiting room, degraded view) rather than a crash.
4. Regulatory & Compliance Requirements
PCI-DSS: Secure handling of payment tokens (offloaded to external Payment Gateway).
Idempotency & Auditing: Every order request must have strict audit logging for fraud prevention and financial compliance.
Step 2: Data Flow and Architecture Definition
1. High-Level Component Diagram
2. End-to-End Data Flow
Phase A: The Read Path (Before/During Deal)
The user requests the Time-Deal detail page.
The request hits Cloudflare CDN. Static assets and JSON metadata of the promotion are served directly from the Edge cache.
If the cache expires, the request goes to the API Gateway, which fetches the data from the Redis Read Replicas (Cache-Aside Pattern). The database is never queried directly for product details.
Phase B: The Write Path (Order Submission)
The user clicks "Buy Now".
The request passes through the API Gateway which validates the JWT token and checks the rate limits.
Traffic Control: If traffic exceeds the threshold, the Virtual Waiting Room (Queue) intercepts the request and queues the user, letting a designated batch through per second.
Inventory Reservation (Fast Path):
The Order Service executes a Lua Script on Redis (Master) to atomically check and decrement the stock:
local stock = tonumber(redis.call('get', KEYS[1]))
if stock and stock > 0 then
redis.call('decr', KEYS[1])
return 1 -- Success
else
return 0 -- Out of stock
end
If Redis returns 0, the request is rejected immediately with a "Sold Out" response ($<50\text{ ms}$).
If Redis returns 1, the stock is secured.
Asynchronous Order Pipeline (Slow Path):
The Order Service generates an Order ID, pairs it with an Idempotency Key, and publishes an Order_Created event to Apache Kafka.
The user receives a 202 Accepted response with an Order Token, and the UI displays a "Processing..." screen.
Persistence:
Order Processor Workers consume messages from Kafka in batches.
Workers write the transaction to the PostgreSQL Database within a database transaction (creating the order record, reducing actual DB inventory, creating payment pending record).
Once persisted, a WebSocket or SSE (Server-Sent Events) notification is sent to the client: "Order Prepared. Proceed to Payment."
Ensures absolute ACID compliance for final financial and inventory state. Handled via managed instances with high-IOPS storage.
Multi-AZ deployment. Write-heavy scaling achieved through connection pooling (PgBouncer).
Cache & In-Memory DB
Redis Cluster
Extreme read/write throughput ($100,000+\text{ QPS}$ per node) to serve as the single source of truth for real-time inventory decrement.
Persistence configured to AOF (Everysec) + RDB. Clustered with replication (1 Master, 1 Replica per shard).
Message Queue
Apache Kafka
Extreme write throughput, distributed partitioning, guarantees message ordering per partition (sharded by promotion_id).
acks=all for durability. Replication factor of 3. Consumers configured in Consumer Groups matching partition counts.
Search Engine
Elasticsearch
Removed completely from the checkout hot-path to avoid cluster degradation. Used strictly for post-deal analytics.
Replicated asynchronously from PostgreSQL DB.
Step 4: Scalability, Latency, and Cost Trade-offs
1. Database Sharding Strategy
Order & User Database: Sharded horizontally by user_id % N to avoid single-point bottlenecks on writes.
Inventory Database: Kept unsharded but separated physically from the main order database to isolate the transaction IOPS.
2. Multi-Tier Load Balancing
Layer 4: AWS Network Load Balancer (NLB) handles millions of raw TCP connections.
Layer 7: Envoy proxy running as API Gateway handles SSL termination, routing, and header-based rate limiting.
3. Horizontal Pod Autoscaling (HPA) and Pre-warming
The Issue: Reactive auto-scaling based on CPU/Memory is too slow for 1-second promotion spikes. The pods will crash before they scale.
The Solution: Pre-Warming.
30 minutes before the time-deal starts, a scheduled script pre-warms the Kubernetes nodes and scales the Order Service deployment to its estimated peak capacity (e.g., from 5 pods to 150 pods).
Redis connection pools are initialized and pre-warmed.
4. Edge Offloading via CDN
All static assets, scripts, images, and non-personalized API responses (such as /promotions/{id}) are cached at CDN Edge servers with a short TTL (Time-To-Live) of 10 seconds. This absorbs 95% of read requests before they even reach the origin servers.
5. Architectural Trade-offs
Consistency vs. Latency Trade-off: We use Redis as a transient scratchpad for high-speed stock allocation. If Redis crashes, there is a minor risk of state discrepancy with PostgreSQL. We accept this small risk (mitigated by AOF replication) in exchange for maintaining sub-200ms latency.
UX Trade-off (The Waiting Room): Instead of processing all requests synchronously, users are queued. This trades immediate confirmation for guaranteed system stability and lower cloud infrastructure costs.
Step 5: Monitoring, Security, and Compliance
1. Monitoring & Observability Architecture
Dashboards (Grafana / Datadog):
System Health: CPU, Memory, Disk IOPS of DBs, Network I/O.
Business Metrics: Orders created/sec, Sold-out progression speed, payment success rate.
Bottleneck Metrics: Kafka Consumer Lag (critical metric; if lag increases, scale workers), Redis CPU utilization (Lua execution times), Active DB Connection Pool Count.
Alerting Triggers (PagerDuty + Slack):
P1 Alert: Kafka consumer lag $> 20,000$ messages.
P1 Alert: HTTP 5xx error rate $> 1\%$ for more than 10 seconds.
P2 Alert: Redis CPU usage $> 80\%$.
2. Security & Anti-Abuse Layers
Bot and Scalper Protection:
WAF rules enabled on Cloudflare to detect headless browsers, credential stuffing, and repetitive scraping IPs.
Implementation of advanced CAPTCHA (e.g., Cloudflare Turnstile) right before the "Buy Now" button becomes active.
Rate Limiting:
Implemented at the API Gateway level using a Token Bucket Algorithm.
Limits: Max 5 checkout requests per user ID / IP per minute.
Idempotency Engine:
The API client must send a unique X-Idempotency-Key for every checkout submission.
The API Gateway checks this key against Redis. If the key exists, it returns the cached response of the previous request instead of reprocessing it.
3. Audit Logging & Compliance
Audit Trail: Every change in inventory status (allocation, rollback, final capture) is written to an append-only transaction ledger in PostgreSQL with the operator/user ID and timestamp.
PCI-DSS Isolation: No credit card data enters the core system. All payment screens are handled via hosted iframes provided by Stripe/Adyen. The system only stores secure, non-reversible transaction reference tokens.
Final Architecture
1. Redis Cluster: The Fast Path (Instant Inventory & Idempotency Check)
Atomic Stock Decrement: To ensure zero overselling under high concurrent traffic, the Order Service executes an atomic Lua script directly on the Redis Master. Redis checks the available stock and decrements it instantly in memory in less than 50 milliseconds. If the stock is 0, it fails fast and rejects the request immediately.
Idempotency Gatekeeping: It prevents duplicate orders (e.g., if a user mashes the "Buy Now" button) by checking unique idempotency keys in-memory before letting a request through.
Why DB isn't used here: A relational database would choke on 50,000+ write QPS due to row-locking bottlenecks and connection limits. Redis handles over 100,000+ QPS easily.
2. Apache Kafka: The Slow Path (Asynchronous Buffering & Durability)
Traffic Shaving / Decoupling: Once Redis confirms that stock has been successfully secured, the Order Service doesn't wait for the slow process of saving the order to the database. Instead, it immediately hands off an Order_Created event to Kafka and returns a 202 Accepted ("Processing...") message back to the user.
Protecting the Database: Kafka acts as a massive shock absorber. It buffers the massive wave of successful order requests, allowing downstream Order Processor Workers to consume those messages in controlled, stable batches and write them safely into PostgreSQL without crashing the database.
3. What does it mean for the traffic shaper?
In this architecture, the Virtual Waiting Room acting as a Traffic Shaper (or Queue Gate) means it controls the velocity and volume of requests flowing into the core application services.
Instead of allowing a massive, uncontrollable spike of traffic to hit the backend all at once, it shapes the traffic into a steady, predictable stream. Here is exactly how it functions: