Problem Statement
Design a system where users can browse events, select seats or general admission tickets, and complete purchases — similar to Ticketmaster. The tricky part is handling thousands of people trying to buy the same limited tickets at the same time, especially during flash sales for popular concerts or sports events.
Your system needs to let users hold tickets temporarily while they check out, release those holds if they abandon the purchase, and guarantee that no two people end up with the same seat. It also needs to handle payment processing, send confirmations, and keep the seat map updated in real time for everyone viewing it.
Key Requirements
Functional
- Event discovery -- users can search and browse events by date, location, genre, and keyword
- Seat selection and availability -- users see a live seat map or available ticket count that updates as others book
- Temporary hold -- selecting a ticket reserves it for a short window (e.g., 5-10 minutes) while the user completes checkout
- Purchase and confirmation -- users pay, receive a confirmed booking, and get digital tickets via email or app
Non-Functional
- Scalability -- support tens of thousands of concurrent users during popular event on-sales
- Consistency -- no double-selling of the same seat, even under heavy concurrent load
- Latency -- seat availability checks and hold placement should respond in under 500ms
- Reliability -- payment failures or crashes must not leave tickets permanently locked or bookings in a broken state
What Interviewers Focus On
Based on real interview experiences, these are the areas interviewers probe most deeply:
1. Preventing Double-Booking Under Heavy Contention
When a hot event goes on sale, hundreds of users may click on the same seat within seconds. The interviewer wants to see how you prevent two people from buying the same ticket.
Hints to consider:
- Use optimistic concurrency control or compare-and-swap operations on seat records to detect conflicts
- Consider a reservation pattern: atomically mark a seat as "held" with a TTL, so it auto-releases if checkout is abandoned
- Think about how to scope your locks narrowly — locking a single seat is better than locking an entire section
- Discuss what happens when a hold expires at the exact moment a user submits payment
2. Managing Temporary Holds and Expiration
Users need time to enter payment details, but you cannot let abandoned holds block inventory forever. Getting the hold lifecycle right is essential.
Hints to consider:
- Store holds with an expiration timestamp and use background sweepers or TTL-based eviction to reclaim them
- Think about race conditions: what if the user submits payment 1 second after the hold expires?
- Consider using Redis with TTL keys for fast hold management, backed by a durable database for the final booking
- Discuss how to communicate hold countdown to the user via WebSocket or polling
3. Real-Time Seat Map Updates
Users viewing the seat map expect to see changes as others book or release seats. Stale data leads to frustration when users select a seat that is already taken.
Hints to consider:
- Use WebSockets or Server-Sent Events to push availability changes to connected clients
- Consider a pub/sub system (like Redis Pub/Sub) where seat state changes broadcast to all viewers of that event
- Discuss the trade-off between pushing every individual seat change vs. batching updates every few seconds
- Think about how to handle reconnection and catching up on missed updates
4. Payment Flow and Failure Recovery
Checkout involves multiple steps: hold confirmation, payment authorization, ticket issuance. Any step can fail, and the system must recover gracefully.
Hints to consider:
- Model the checkout as a state machine: held → payment_pending → confirmed (or expired/failed)
- Use idempotency keys so retrying a payment does not double-charge the user
- Consider an outbox pattern to reliably trigger downstream actions (email, ticket generation) after successful payment
- Discuss how to handle partial failures — e.g., payment succeeds but ticket generation fails
Suggested Approach
Step 1: Clarify Requirements
Ask about expected scale (how many concurrent users per event on-sale?), whether seats are assigned or general admission, hold duration, and payment requirements (deposits vs. full payment). Clarify if features like waiting rooms or queuing during flash sales are in scope.
Step 2: High-Level Architecture
Sketch separate services for event catalog/search, inventory management, checkout/payment orchestration, and notifications. Use a fast in-memory store (Redis) for seat holds and real-time state, a relational database (PostgreSQL) for durable booking records, and a message queue (Kafka) for async workflows like email delivery and analytics.
Step 3: Deep Dive — Inventory Contention
Walk through what happens when a user clicks "Book" on a seat: the system attempts an atomic conditional write to mark the seat as held. If another request already claimed it, the operation fails and the user is told the seat is taken. Discuss how this scales across event sections using sharding and how expired holds are swept back to available.
Step 4: Address Secondary Concerns
Cover admission control (virtual waiting room) for flash sales, monitoring and alerting for booking success rates, fraud prevention, and graceful degradation if downstream services (payment gateway) are slow.
Related Learning
If you want to deepen your understanding of the patterns used in this problem, check out these resources:
- Yelp System Design — covers search and discovery patterns applicable to event browsing
- Bookstore System Design — covers similar inventory contention and checkout flow patterns
- Caching — essential for real-time seat availability at scale
- Message Queues — key to decoupling payment from ticket delivery