-> The user should be available to check the availability of seats for by registering to queue.
-> The user can select seats and the seats remain reserved till the user checkout.
-> Seats availability will be refreshed real time
-> The user can pay for the selected seats
-> After paying and confirm the user will receive notification about order and up coming events notifications
Availability: the system should be available and responsible whenever there is a popular movie or a popular concert.
Consistency: The system should remember the transactions and make sure the double booking seat is not allowed
Scalability: The system should scale in case of a sudden increased traffic.
Latency: The system should mark the available/reserved seats in real time
Security: Only the users which securely logs in can buy tickets
The system should handle 1000 cities globally with 5 events avenues with 10 movies per theater and each movie being played 2 times = 100 000 movies per day.
Supposing each movies has an average of 30 people => 3 millions tickets per day.
Each booking of show results in:
user_id - 8 bytes
date_id - 8 bytes
movie_id 8 bytes
payment_id 8 bytes
seat _id 8 bytes
theather_id 8 bytes
status 8 bytes
=> 256 bytes => 750 000 KB => 750 MB => 1 GB/day
storage for 1 year will be 365 GB only for bookings => 5 years storage 1.8TB
A techinique of cold storage, hot storage can be used to keep historical data.
DAU of the system: 30 millions users that will use the system for at least checking the availability or consult the schedule. Each user does in average 3 requests => 150 millions user a day
Read path: 90 millions req/ day => 150 mil/ 86400 s => 1000 req/s
Write Path: 3 millions req/ day => ~30/s
The system should be consistent and also read heavy.
GET /api/movies/search
GET /api/theater/schedule?movie_id= return the schedule of a theather by movie.
GET /api/theater/availability returns the available/taken seats with a price for each of them.
POST api/theather/reserve_selected_seats(listOf(seats)) will reserve the selected seats
POST api/thether/checkout_reserved(listOf(seats), user_id, amount) -> used to order and finalizaze the checkout process
POST api/payment/booking_id
Authorization header will be used on each request with the JWT of the user logged contains the user claims.
4XX errors will be return in case of an system errors/ 409 Conflict status in case of selecting a reserve seat. 404 for not found resource, 400 Bad request in case of not valid data on reservations or booking
5XX errors will be returned in case of any unhandled errors.
Considering the need for a reliable and consistent system to handle the reservations of the spots and user booking an SQL databased can be employed for the job , E.g. PostgreSQL
A unique constraint and index is placed in the table Spot_reservations preventing to store of a double booking.
Another table prepopulated with with each seat per event is used to do reservations of N minutes when a user selects a seat, being associated with user_id.
We can choose from doing Optimistic locking when reserving the seats and create the bookings or Pessimistic locking to block the rows when updating the reserve seats or doing locking.
Since our system will be also read heavy an Optimistic locking will suits best
Book service will handle the reservation of the seats when the user selects available places till the payment is done(5-15 minutes). The seats are marked as reserved in the database and a real-time update will be shown to other users.
Book Service will also do the booking of the tickets and insert them transactionally into the databse.
Timer Service is the service that will undo the reservations which expired by removing the session data.
Payment Service will handle the payments for bookings
ScheduleService will get all the details about theater, movies played at each theater and the schedule.
NotificationService will send emails to users once the booking is done.
getTheatherSchedule- will be initiated by client, The client will load balance the requests towards an ApiGateway that will route the request to Schedule Service. Since the schedule of an event is an information requests often we check the cache. If the action results in a cache miss we can query the database. When the result of the query is received from db, the ScheduleService updates also the cache before.
bookSeats -> will use to book the seats already reserved and pay for the order. The request will traverse in a similar fashion Load balancer, ApiGateway, to reach BookService. BookService will check the reserved seats in Db will compute the price and return a payment link. When the payment is done another request will finalize the booking.
The BookingService is the most critical service from the application being used to handle the bookings and seat reservations.
For the seats reservations we can add a row for each combination of event, seat that will be used to be locked by a single user, and no two users can reserve the same seat.
Optimistic locking will be used for this action. Optimistic locking consists in a version column added to the row which is used to check that only a transaction with the correct version can update that row, incrementing the version also. The other transactions will hold an older version resulting in not being able to update.
For the booking service another table will be used to insert the booked seats, the composed unique index per event_id and seat_id will not allow the insertion of duplicate bookings per seats.
Load balancing is used here to increase the scalability of the system by balancing the load to multiple instances when horizontal scaling is needed.
The cache is used to improve the latency of frequent query data as movies played in theater, details about movies, or schedule.
We favor the SQL database with strong consistency for our reservations and booking system. Although this a system where is read heavy we can use cache to improve the latency.
The optimistic concurrency can offer a better performance not locking the rows for a long period.
The Optimistic locking is harder to implement than pessimistic locking and it is harder to propagate the errors to the users.
Web sockets or SSE is used to update the user real time of the available seats.
Will be hard to scale Websockets real-time servers when horizontal scaling will be employed.
Cache stampede when multiple items expire from cache, which can be solved either jittter adding random expire times or prepopulating the cache. The update of the cache will be locked so only 1 request can query and update the other will have to wait.
The write path can be improved by making the booking asynchronously being added to a queue and
CDN can be used to cache static data.
Analytics and reports service can be added.
Sharding can used to scale the database using the city as a partition key.