System requirements
Functional:
- The user can create an account that keeps his info, payment information, and tickets.
- The system can process payments
- The user is able to view upcoming movies, their trailers, locations, and show times.
- The user can choose a movie time and location and purchase a ticket.
- The user can view his upcoming events.
- After an event passed, the user should not be able to use the ticket anymore.
Non-Functional:
- High consistency - the system should constantly update the number of tickets available etc., to prevent double/over booking.
- Availability
- 2:1 read-write distribution.
- traffic is unevenly distributed. We have active users and passive users.
Capacity estimation
Assume 10 million accounts
Assume 100 million purchases per month
Assume a ticket size is roughly 50 bytes (user_id, purchase_time, show_id, price, seat)
5 billion bytes of purchase data per month.
60 billion bytes a year
API design
account API - will be connected to an authentication service and will manage the process of opening a new account and logging into an existing one.
Transaction API - will be connected to a purchase service and will manage the booking of tickets.
Read API - allows a user to browse the movies, their locations, their trailers, and showtimes.
Database design
I choose to use a relational DB since we have a lot of data and little room for flexibility. The data needs to be highly structured and we do not need to allow for duplicates. we also want to support complicated joins
Tables:
Users: userid, username, password, email, previous_purchases, upcoming_event, payment_info, birth_date
Movies: movie_id, release_date, trailer, length
Theaters: t_id, location, presenting_movies
presenting_movies: movie_id, theater, times
High-level design
The client through the web server can create an account and also access an existing account.
The client through the web server can purchase a movie to a ticket which will be posted to his account.
The client through the web server can browse the upcoming movies and their times.
The Accounts API has an authentication service and is also connected to the DB.
The transactions API has a payment service and is also connected to the DB.
The read API is connected to the DB.
there DB has some master-slave replicas that help with scaling. It also has a cache and an object storage. There is a CDN connected to the object storage.
Request flows
browsing for movies:
The user will be redirected to the read API, which will query the DB and present the available movies. The API will allow filtering based on movie, location, time. The object storage will be used for example to store movie trailers.
Purchasing a ticket:
The user will be redirected to the transaction API which will query the DB and using the payment service will charge the user. The tracker service will update the capacity left at the theater and the seats available.
opening/logging into an account:
the user will be redirected to the accounts API and the authentication service will assist the user. New accounts will be stored in the DB.
Detailed component design
read API: connected to the database and allows filtering based on movie name, time, theater etc. Queries the DB and presents the relevant information. To fetch static content like trailers, the CDN and the object storage will be called.
tracker service: keeps track of the available seats left in a theater. It keeps a dictionary of theaters for every location. each theater is a dictionary as well with the seats as key as a boolean "status" as values to indicate if they are taken or not.
To support the DB we have master-slave replicas that will serve all the read requests and also a cache that can save the most popular movies at the moment to reduce access to the DB.
Trade offs/Tech choices
chose a RDB instead of a NoSQL.
Failure scenarios/bottlenecks
Bottlenecks are possible at the DB. We have master-slave replicas which means that the slaves can only serve the read requests. If many purchases happen at once, the master DB will be overloaded.
Future improvements
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?