Classic design · Mid
Ticket sales for a major event (Ticketmaster)
Classic interview design. Key points: reservations and concurrency, and overload control.
Short answer
Classic interview design. Key points: reservations and concurrency, and overload control. An online ticketing site shows events, lets you search, and sells tickets. The hard part is not listing events: it is, when many people want the same seat at the same time, giving each seat to just one person without bringing the system down.
01 · CONTEXT AND REQUIREMENTS
Selling the same seat only once
An online ticketing site shows events, lets you search, and sells tickets. The hard part is not listing events: it is, when many people want the same seat at the same time, giving each seat to just one person without bringing the system down. This case is a classic interview topic in requirements gathering.
There are three core functional requirements: view events, search events, and book tickets. Among the non-functional ones, the source separates two behaviors: search and viewing prioritize availability, while booking prioritizes consistency, so there is never a double sale. There are also scale and latency goals: support a very popular event, fast search, and a read-heavy system.
02 · ENTITIES AND FIRST DESIGN
From event to seat
O data model revolves around event, venue, artist, ticket, and booking. The source lists entities such as event, artist, and venue, plus user, ticket, and booking. Each seat in the venue becomes a ticket when the event is created, and the client combines the venue map with the state of each ticket to draw the seat selection.
A API has read queries (view an event, search events) and one write operation that books: a POST to /bookings with the identifier of the chosen ticket.
The person opens an event page; the request goes through the gateway and reaches the events service.
The events service reads the event, venue, and tickets from the database to build the seat map.
When a seat is chosen, the booking request goes through the gateway to the bookings service.
The bookings service writes to the same database. The open question is how to prevent two people from getting the same seat.
This first version separates reading from booking, but still does not say how to hold a seat while the person pays. That is the central problem of the case.
03 · BOOKING WITHOUT DOUBLE SALES
From the database lock to the lock with an expiry
Many candidates' first idea is to lock the ticket row in the database while the person pays. The source treats it as a bad solution: long locks overload the database and increase the risk of contention and deadlock.
A better alternative marks the ticket as reserved, with an expiration time, and uses a periodic job to return expired ones to inventory. The limit, according to the source, is the lag between expiration and the row being fixed, which is bad for popular events. A variation avoids the job: a short transaction accepts the ticket if it is available or its reservation has already expired, which guarantees a single reserver.
The solution the source adopts is a distributed lock with a TTL in Redis. The Redis expires keys on its own, and the command to write the key only if it does not exist, with an expiry, is atomic: only one client gets it. The database ends up with only two ticket states, and in-progress reservations live in Redis.
| Criterion | Row lock in the database | Status with expiration | Distributed lock with TTL |
|---|---|---|---|
| How it holds the ticket | Keeps the transaction open during payment | Marks the ticket as reserved with an expiration time | Writes a key with an expiry to an in-memory store |
| Limit pointed out | Contention, deadlock, and database load | Lag in returning expired reservations | Requires one more component and an extra read to show the map |
| Release | Only at the end of the transaction | By the periodic job or by the check on the next booking | Automatic, when the key expires |
The person picks a seat on the map; the booking reaches the bookings service.
The bookings service tries to write to Redis a key with the ticket identifier and a ten-minute expiry. Only one attempt wins.
With the lock obtained, the service writes an in-progress reservation to the database and the person proceeds to payment.
When payment is confirmed, the ticket becomes sold, the booking is confirmed, and the lock is released.
If time runs out without payment, Redis releases the key on its own and the ticket becomes available again.
Two robustness details. The payment notification arrives via a webhook that can be resent, so the handler must be idempotent. And if the reservation expires during payment, the source proposes an automatic refund, besides setting a generous TTL.
04 · READ AND SEARCH
Cache, search index, and CDN
Since traffic is read-dominated, the events service is stateless and scales horizontally behind a load balancer. Heavily read, rarely changed data, such as event and venue details, are good candidates for cache, read-through style: a cache miss reads the database and updates the cache.
For busca, the source starts from database indexes and arrives at a full-text search engine, such as Elasticsearch, kept in sync with the SQL database by change data capture (CDC). For repeated searches, results can be cached and, when it makes sense, placed in a CDN closer to whoever is searching.
The search or event page goes through the CDN first, which may already have the result of a repeated search.
On the read path, the events service queries the cache. If the event is there, it responds without touching the database.
If it is not, the service reads from the database and writes the result to the cache for the next people.
The text search goes to the search index, which answers faster than scanning the database.
Database changes are copied to the index through change data capture, so searches do not go stale.
05 · EXTREMELY POPULAR EVENT
Real-time map and virtual queue
For the seat map to reflect other people's bookings without reloading the page, the source proposes pushing updates to the client with Server-Sent Events. It works well for moderate events; for extremely popular events, the map empties in an instant and the experience is still bad.
For that case, the source proposes a virtual waiting queue enabled by administrators. The queue sits in front of the bookings service, keeps a persistent connection with those waiting, lets people through gradually, and records the admitted ones. The bookings service checks this record and rejects anyone who did not go through the queue.
At a hotly contested event, the person who requests the booking page first enters the virtual queue, before seeing the map.
The queue service keeps an open connection and stores the order of arrival in Redis so it can report the position.
Gradually, people leave the front of the queue and are marked as admitted, with an expiry.
The bookings service checks the admitted record and rejects anyone who did not go through the queue.
Those admitted follow the normal flow: lock with an expiry, in-progress reservation, and payment.
06 · LIMITS OF THE DESIGN
What can still go wrong
The TTL lock has a read cost: the map has to combine the database with Redis, which adds a trip to Redis on the read path. There is also the TTL choice: if it expires during payment, the purchase fails and the refund comes into play. The source recommends a generous TTL and, better still, extending the lock when payment starts.
Frequently asked questions
What is Ticket sales for a major event (Ticketmaster)?
Classic interview design. Key points: reservations and concurrency, and overload control.
What does the Ticket sales for a major event (Ticketmaster) design cover?
It is organized in these sections: Selling the same seat only once, From event to seat, From the database lock to the lock with an expiry, Cache, search index, and CDN, Real-time map and virtual queue, and What can still go wrong.
How long is Ticket sales for a major event (Ticketmaster) and what level is it?
It takes about 14 minutes to read and is rated Mid level.
Now design it yourself
Run this case as an interview in the System Design school: you make the decisions, the tutor challenges them and you see how your design scores.