Systems Design: Ticketmaster

Cghzqzd
4 min readMay 31, 2021

--

READ MF!

Requirements

Functional

  • User selects a city and sees all the movies in that city
  • User selects a movie and sees all theaters and showtimes
  • User selects a particular show and books tickets from the seating arrangement and availability.
  • User gets 5 minutes to make a payment

OR

  • waits for 30 mins max for seats to become available.
  • Waiting customers should be serviced in first come first serve manner.

Non-functional

Availability

99.99

Latency

100ms

Estimation

Storage

Let’s assume we have 500 cities and each city has 10 theaters. Each theater has 2k seats and has 10 shows per day.

Let’s assume each booking needs 50 bytes. We also need to store movie and theater metadata. So let’s take 100 bytes total.

500 cities * 10 theaters * 2k seats * 10 shows * 100 bytes = 5000000 * 2000 = 10 000 000 000 = 10 GB /day

For 1 year, 10GB * 400 = 1TB

Read QPS

3 * write = 30k qps

Write QPS

Popular movies might get 1 million ticket sales in 10 minutes

1 million active users 1M / 10/6 = 1.5k write QPS

API Spec

/domain/api/v1/city/:city/movies/:movieId?lat=43.2&lng=23.2

Database/Design

Database

Design

Scaling up and handling multiple users

We sold the same seat to both Alice and Bob!

Easy solution! When someone submits their payment info to purchase a seat, do a last-minute check to see if we already sold the seat.

There’s still a potential issue if two people actually submit their payments super close to each other. Both users could hit this line at the same time:

if the seat is marked as available in the seats table:

They’d both pass that check, continue into the block, and charge the user’s card. So we’d be selling the same seat twice again. Oof.

Transactions!

when the user submits their payment for a seat:
start a database transaction

if the seat is marked as available in the eats table:
charge their card
and mark the seat as unavailable
else:
redirect the user to the seat selection page
and say "Sorry, that seat's already taken!"

end the database transaction, committing the changes

Cannot catch a break!

Bad user experience.

One way to fix this is mark the seats in reserved state. We could add in a timeout. Once a user selects a seat, we’ll block anybody else from choosing the same one, but only for a short amount of time (say, 5 minutes). After that, the user’s hold on the seat goes away, and they’re no longer guaranteed the seat.

One option would be to periodically run through all the entries in the Seats table, find all the entries with a seatStatus of reserved and a seatSelectionTime more than 5 minutes ago, and clear the reservation. Like this:

for all seats
if both - seat status is 1 (reserved but not purchased) AND
- seat selection time is more than 5 minutes ago, then
- set seat reservation time to null
- set seat status to 0 (unreserved)

Another option is to let seats linger in the “reserved but not yet purchased” state until someone else tries to select the seat. Then, we’ll let them select the seat if it is:

  • Available (with a seatStatus of 0), or
  • Reserved (with a seatStatus of 1) but expired (seatSelectionTime is more than 5 minutes ago)

Both of these options are reasonable. The first one could be preferable because it’ll keep our database tidier (we’ll have fewer seats in the intermediate reservation step). But it also adds extra overhead to the Seats table due to the scanning step, which requires making extra queries and updates that aren’t strictly needed. The second option avoids this overhead entirely, only timing out tickets that have been requested by someone else.

--

--

No responses yet