· SWE Editorial · System Design  · 6 min read

Design a Ticketing System: System Design Interview Guide

How to answer the ticketing system interview question: seat reservation, concurrency control, payment timeouts, waitlists, and venue layout modeling.

How to answer the ticketing system interview question: seat reservation, concurrency control, payment timeouts, waitlists, and venue layout modeling.

“Design a ticketing system like Ticketmaster or StubHub” is a favorite interview prompt because it looks like a simple CRUD problem but is secretly a hard concurrency problem. Thousands of users can try to buy the same seat for a popular concert within milliseconds of each other, and the system must guarantee exactly one of them succeeds. This guide walks through how to structure a strong answer.

Why This Question Is Deceptively Hard

At first glance, “reserve a seat” sounds like a single database write. The complexity comes from three intersecting requirements: correctness under massive concurrent demand (no seat sold twice), a good user experience (a seat held in your cart shouldn’t be snatched away while you’re entering payment details), and scale (a popular on-sale event can produce more concurrent requests per second than the rest of the year combined).

Step 1: Clarify Requirements

Ask the interviewer:

  • Scale of a single on-sale event. Is this “10,000 seats, moderate demand” or “50,000 seats, a viral reunion tour with 2 million people refreshing at 10am”?
  • Reservation hold time. How long does a user get to complete payment before their seat is released back to the pool?
  • Seat-specific vs general admission. Reserved seating is a much harder concurrency problem than “just deduct from a counter.”
  • Waitlist behavior. Should sold-out events let users queue for release inventory?

These answers shape whether you need a queueing/virtual-waiting-room layer in front of the checkout flow at all, which is often the single most important design decision for high-demand events.

Step 2: Model the Venue and Seat Inventory

For reserved seating, model the venue as a hierarchy: venue → section → row → seat. Each seat has a status: available, held, sold. This is the core piece of state the entire system protects.

For general admission or capacity-based tickets (no specific seat), model inventory as a simple counter per ticket tier, which is a much easier concurrency problem (decrement-if-positive) than seat-level locking.

Step 3: Seat Reservation and Concurrency Control

This is the heart of the interview. When a user clicks a seat, the system must atomically transition it from available to held and prevent any other user from also holding it. There are three common strategies.

Pessimistic locking (database row lock). SELECT ... FOR UPDATE on the seat row, transition its status, commit. Simple to reason about and strongly consistent, but if the transaction is slow or the lock is held too long, it creates contention that hurts throughput during a hot on-sale.

Optimistic locking (compare-and-swap). Read the seat’s current status and version number, then issue an UPDATE ... WHERE status = 'available' AND version = X. If zero rows are affected, someone else won the race and the client retries with a different seat. This avoids holding locks but requires a retry loop on the client or server, and can produce a lot of failed writes under extreme contention.

Distributed lock (e.g., Redis-based). Acquire a short-lived lock keyed on the seat ID before touching the database. This decouples the “who gets to reserve this seat” decision from the database entirely, which is useful when the actual booking involves multiple downstream steps (seat hold, price calculation, promo code validation) that shouldn’t all happen inside one long database transaction.

In an interview, name all three, then justify optimistic locking or a distributed lock as your primary choice for a hot on-sale, since pessimistic database locks tend to become the bottleneck exactly when you need throughput most.

Comparison Table

ApproachThroughput under contentionConsistency guaranteeImplementation complexityBest fit
Pessimistic DB lockLow (lock contention)StrongLowLow-demand events, small seat maps
Optimistic locking (CAS)Medium-high (retries on conflict)StrongMediumMost seat-based ticketing systems
Distributed lock (Redis)High (short lock hold time)Strong, if lock TTL tuned correctlyMedium-highHigh-demand on-sales, multi-step booking flow
Counter decrement (GA tickets)Very highStrongLowGeneral admission, capacity-only inventory

Step 4: Payment Timeout and Seat Release

Once a seat is held, the user typically has 5-10 minutes to complete payment. This needs a reliable expiration mechanism:

  • Store the hold with an expiration timestamp, and use a background sweeper job or a TTL-based mechanism (e.g., a Redis key with expiry, or a delayed message in a queue) to release seats whose hold has lapsed.
  • On successful payment, transition the seat from held to sold and cancel the pending expiration.
  • Handle the edge case where payment succeeds right as the hold is expiring — this needs the payment confirmation path to check “is this hold still mine” before finalizing, and to re-extend or override the expiration atomically.

Step 5: Waitlist for Sold-Out Events

For events with more demand than seats, or where fans want re-release inventory (someone else’s held seat expiring, a refund becoming available):

  • A FIFO waitlist queue per event captures interested users in order.
  • When a seat becomes available, the system notifies the next N users in the queue with a short time-boxed window to claim it, then moves to the next batch if unclaimed.
  • This is fundamentally a producer-consumer pattern: seat releases are the “supply” event, and the waitlist is a consumer that needs to process supply fairly and quickly.

Step 6: Venue Layout and Read Path

The seat map itself (which seats exist, their coordinates, pricing tier) is read far more often than it’s written. Cache the static venue layout aggressively — it almost never changes for a given event — and only query the database (or a fast in-memory store) for live seat status, which does change constantly during an on-sale.

For a deeper architectural walkthrough of how these pieces fit together end to end — including where queues, locks, and event sourcing show up in the data flow — see Design a Ticketing System: Architecture and Data Flow.

Failure Modes to Call Out Proactively

  • Overselling under retries. If a client times out waiting for a hold confirmation and retries, make sure the retry is idempotent (same idempotency key) so it doesn’t accidentally hold two seats.
  • Hot on-sale traffic spike. A virtual waiting room (rate-limiting entry into the actual booking flow) is a standard mitigation that keeps backend load predictable even when demand is 100x normal.
  • Payment provider outage. Seats should not remain held indefinitely if the payment provider is down; a circuit breaker plus a shorter fallback hold time protects inventory from being locked up by a dependency failure.

Sample Interview Answer Structure

  1. Clarify demand scale, hold time, seat-specific vs GA — 2 minutes.
  2. Model venue hierarchy and seat status state machine — 2 minutes.
  3. Propose optimistic locking or distributed locks for seat reservation, with justification — 4 minutes.
  4. Explain hold expiration mechanism — 2 minutes.
  5. Cover waitlist design for sold-out events — 2 minutes.
  6. Proactively flag overselling, traffic spikes, payment outages — 3 minutes.

Practice More

The 0-to-1 SWE Interview Playbook (Amazon: https://www.amazon.com/dp/B0H256Z1MF?tag=sirjohnnymai-20) includes worked-through concurrency-heavy prompts like this one, with the same interviewer-lens breakdown used throughout this guide.

Key Takeaways

  • The core challenge is atomic seat reservation under extreme concurrency, not CRUD.
  • Optimistic locking and short-lived distributed locks scale better than pessimistic database locks during hot on-sales.
  • Hold expiration needs a reliable sweep mechanism, and must handle the race between “hold about to expire” and “payment just succeeded.”
  • A FIFO waitlist with time-boxed claim windows is the standard pattern for re-released inventory.
Back to Blog

Related Posts

View All Posts »