Design Ticketmaster & Flash-Sale Reservation
Design a high-concurrency event ticketing platform like Ticketmaster or BookMyShow. The system must handle sudden 1,000,000-user traffic surges attempting to purchase 50,000 seats at the exact same second. It must guarantee strict transactional consistency (zero double-booking), handle user cart abandonment, and prevent database deadlocks.
Flash-sale checkout engine handling 50,000 concurrent purchase transactions for 500 limited sneaker SKUs. Failure cascade dynamic: Burst → Pool Saturated → Queue Bloat (10k) → STW GC → 💥 504 Timeouts.
Core Functional Requirements
- ✓Zero double-booking: A specific seat can never be purchased by more than one user.
- ✓Reservation hold: When a user selects a seat, it is locked for 5 minutes to complete payment.
- ✓Abandoned inventory release: If payment fails or the user leaves, the seat automatically becomes available again.
- ✓High throughput: Protect origin relational databases from thundering herd saturation.
A three-tier high-concurrency reservation architecture: 1. A Virtual Waiting Room buffers massive thundering herds and throttles traffic into the booking service; 2. An in-memory atomic reservation engine (Redis Lua) verifies available inventory in sub-milliseconds; 3. Pessimistic row-level database locking (SELECT FOR UPDATE) executes the finalized 5-minute seat hold in PostgreSQL, backed by a delayed message queue for automatic inventory release upon abandonment.

Hardened Implementation Steps
- 1Virtual Waiting Room: Incoming users are queued in a distributed token bucket system. A rate limiter admits a controlled stream (e.g. 2,000 users/sec) to the seat selection service.
- 2Live Map Browsing: Read seat availability from an edge Redis cache; WebSocket connections push real-time seat lock updates to all active viewing clients.
- 3Pessimistic Row Lock: When user taps "Reserve", execute a transaction in PostgreSQL using row-level locking (SELECT FOR UPDATE) to transition seat status from AVAILABLE to LOCKED with a 5-minute lease.
- 4Delayed Message Queue: Schedule a message in AWS SQS with a 5-minute delay. If payment confirmation has not arrived when the delayed message is consumed, revert seat status to AVAILABLE.
Production Code Contrast & Implementation
-- PostgreSQL syntax for transactional row-level reservation locking
BEGIN TRANSACTION;
-- Select and lock the specific seat row against concurrent transactions
SELECT seat_id, status
FROM seats
WHERE seat_id = 42 AND event_id = 1001 AND status = 'AVAILABLE'
FOR UPDATE;
-- If row is returned, seat is available: lock it with a 5-minute expiration
UPDATE seats
SET status = 'LOCKED',
locked_by_user = 999,
lock_expiry = NOW() + INTERVAL '5 minutes'
WHERE seat_id = 42;
COMMIT;Architectural comparison of naive unconstrained allocations versus production-hardened mechanical sympathy.
Architectural Decisions & Trade-Offs
- ⚖Ingress Admission: Naive unconstrained buffering causes queue bloat and GC exhaustion. Mitigation: Bounded ingress gate with fast non-blocking shedding.
- ⚖Resource Strategy: Static capacity allocations collapse under brownouts. Mitigation: Dynamic adaptive limits scaling to real-time physical bounds.
- ⚖Outage Impact: Cascading lock convoys and memory saturation. Mitigation: Isolated failure domains keep P99 latency flat and protected.
Alternatives Evaluated
- →Naive Approach: Executing 'SELECT stock FROM inventory WHERE item_id = 101 FOR UPDATE'. 50,000 database transactions serialize behind a single InnoDB/PostgreSQL row l
- →Production-Hardened Pattern: Offload real-time inventory reservation to an in-memory single-threaded atomic engine (Redis Lua script via DECRBY), issuing an ephemeral 15- minute l
Operational Hazards & Mitigations
- ⚠Cascading Failure: Executing 'SELECT stock FROM inventory WHERE item_id = 101 FOR UPDATE'. 50,000 database transactions serialize behind a single InnoDB/PostgreSQL row lock. HikariCP connection pool (100 connections) exhausts in 12ms; database CPU hits 100% on deadlock detection, crashing the API.
- ⚠Breakdown Chain: Burst → Pool Saturated → Queue Bloat (10k) → STW GC → 💥 504 Timeouts
- ⚠Shedding Failure: Without fast rejection at the boundary, queued dead work triggers multi-second GC pauses, CPU thrashing, and cascading 504 Gateway Timeouts.
How does the system enforce physical resource boundaries under sudden downstream latency brownouts?
Extension Implementation Steps
- 1Track real-time latency gradients and inflight concurrency.
- 2Reject excess traffic at the ingress boundary within <0.1ms.
- 3Monitor P99 latency and verify autonomous recovery when downstream pressure subsides.
Follow-Up Trade-Offs
- ⚖Architectural Invariant: "Never acquire relational row locks (SELECT FOR UPDATE) on shared hot counters during peak traffic surges; use in-memory atomic staging."
- ⚖Physical Resource Boundary: Dynamic admission control ensures worker threads never buffer dead requests during downstream brownouts.
Interactive Assessment & Knowledge Check
Test your understanding of the architecture decisions, data patterns, and trade-offs used in Design Ticketmaster & Flash-Sale Reservation.
B+ Tree vs LSM-Tree Storage Engine Trade-Offs
Why do high-throughput write-heavy storage engines (like RocksDB and Cassandra) use LSM-Trees instead of traditional B+ Trees?