System requirements


Functional:

  1. Users can search theaters by entering a location (city or ZIP code) to see the movies that are playing.
  2. After users select a theater, they can select a movie and get the showtime list and the detailed information.
  3. After users select the time, they can see the available seats in the room and select the seats they want.
  4. During the selection of the seats, the seats will be locked to prevent double booking by others. The process would last for 5-10 minutes.
  5. After users select the seats, they can make a payment.
  6. After the payment, they will receive a notification via email or text.



Non-Functional:

  1. The system should be reliable and available for users to browse and buy tickets at any time.
  2. The system should make the availability of seats consistent with the actual situation to prevent mutiple booking. In addition, each order should have a unique global order_id.
  3. Scalability. When there is lack of resource, we can add servers to handle the large number of requests.




Capacity estimation

We can also assume there are 1 million people browsing the platform every day and they will visit the system 10 times and generate one purchasing record each day. So there would be 1,000,000 * 1 * 365 = 3.65 * 10^8 records in each year. Each recrod would be stored for two years. So there would be totally about 10^9 records. Assume each records has 100 KB (0.1 MB) so the total storage would be 10^9 * 0.1 / 1000 = 10^5 GB = 100 TB. We would use about 10 database servers.

QPS = 1,000,000 / 24 / 3600 * 10 = 110. But people tend to visit the system during the free time, so we assume the QPS is 500. And when there are hot movies in the show, I believe the QPS could reach 5,000. So the service servers would also be 10.




API design

  1. /theaters/{zip_code}: will show the list of theaters near the location.
  2. /theaters/{theater_id}/movies: will show the list of movies that are playing in the given theater.
  3. /theaters/{theater_id}/movies/{movie_id}/timeslots: will show the list of time of a given movie in a given theater.
  4. /theaters/{thearter_id}/movies/{movie_id}/timeslots/{time}/seats: will show the available seats in the room.
  5. /orders/{order_id}: will generate an placed order and send the notification to users.



Database design

  1. user table: SQL. Columns: user_id(pk), user_name, email, phone_number, password, created_time, modified_time, last_login.
  2. theater table: SQL. Columns: theater_id(pk), theater_name, location, description.
  3. movie table: SQL. Columns: movie_id(pk), movie_name, genre, language, description.
  4. theater_movie table: SQL. Columns: tm_id, room_id(fk), movie_id(fk), time.
  5. room table: SQL. Columns: room_id(pk), theater_id(fk), type, room_name, room_capacity.
  6. seat table: SQL. Columns: seat_id(pk), room_id(fk), status, seat_code, row_loc, col_loc.
  7. order table: SQL. Columns: order_id(pk), user_id, total_cost, order_time, status, payment_status, payment_method.
  8. order_item table: SQL. Columns: order_item_id(pk), order_id, tm_id(fk), seat_id(fk), ticket_price, ticket_status.
  9. notification table: NoSQL. key: order_id, user_email, user_phone_number, text.



High-level design

You should identify enough components that are needed to solve the actual problem from end to end. Also remember to draw a block diagram using the diagramming tool to augment your design. If you are unfamiliar with the tool, you can simply describe your design to the chat bot and ask it to generate a starter diagram for you to modify...







Request flows

The user will search the theaters nearby according to their location. The request will go to CDN firstly. It contains local theaters and their recent hot movies. Thus, if the user search the movies, CDN may return the results quickly. If the results are not in CDN, then the request will go to redis, because we can assume a user is likely to browse repeated information like theaters, movies, and so on in a short time. It's suitable to store the information in redis. If there are no results in redis, then the request will go to the database and write back to redis. After the user places an order, the request will be sent to a message queue for servers to deal with, and finally the notification will be sent to the user.





Detailed component design

  1. CDN. I use CDN to store the local theaters and hot movies to shorten the query time.
  2. redis. I assume a user will repeat to browse the information during a short time. So I design to use redis. GET requests will go to the redis firstly, and if there are no results in the redis, the requests will query the database and write into the redis. I plan to use a ttl invalidation strategy and the time to live should be 5-10 minutes. For POST requests like selection of seats, the change of status will only happen in redis, and after users place orders, the change will be written back to the database.
  3. message queue. The message queue is used to store the orders temporarily and cut the peak to fill the valley to handle a large number of requests.
  4. data center, users and orders. I prefer to use snwoflake algorithm to generate user and order id because they require unique global id. If a new user or a new order is generated, it will be written to the global master data center, and then separate to other data centers.




Trade offs/Tech choices






Failure scenarios/bottlenecks

Try to discuss as many failure scenarios/bottlenecks as possible.






Future improvements

What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?