List the key functional requirements for the system (Ask the AI for hints if stuck)...
Event Owners:
Can upload movie meta data(name, duration, actor list, etc), seat chart, availability basically inventory management
Users:
View list of movies in their location
Search for a movie by title, actor, day etc
View seating chart
Choose seats to cart
Proceed to book the seat
Payment methods ( UPI, Credit, Debit, Paypal)
History of bookings
Notification for order confirmation etc
List the key non-functional requirements (performance, scalability, reliability, etc.)...
Need low latency
Need high availability for view/search > consistency
Need high consistency > availability for payment
Scalable for peak hours -> concurrency needs to be there for seat booking
Durability ofcourse needed, security needed and fault tolerance as well
Estimate the scale of the system. Consider daily active users, read/write ratio, storage requirements, bandwidth, and any relevant QPS calculations...
Total users = 5M, DAU = 60% DAU so 3M
Concurrent users = 20-25% DAU at peak, so 750k
Booking/second = 2bookings/day = 2*3M = 6M bookings/day = 6M/86400 = 70bookings/sec
At peak = lets say 2-3x more, 210bookings/sec at peak
1 server can handle 50-100k concurrent connections when tuned properly, so 750k can be handled by around 10 servers.
Its a write heavy application as bookings>reads
Define the APIs expected from the system. This is your chance to analyze and define the read and write paths so that you can come up with the high-level design...
View list of movies in their location
this is a get request, user id location are passed with JWT token
GET/movielist
List
Search for a movie by title, actor, day:
This is a get but with some filters
GET/movie?title=Inception&genre=comedy
List
FilterGenre, FilterTitle could be enums
View seating chart:
GET/seat?showId=1
different shows and same show with different times get different show ID
Choose seats to cart Proceed to book the seat:
POST/{}
payload: {userID, showID, seats[seatId1, seatId2,..]}
reserve mechanism here
Payment methods ( UPI, Credit, Debit, Paypal)
Post/{}
payload: {userId, showId, bookingID, paymentType}
strategy pattern can be used here
History of bookings:
GET/orders?from=Date1&to=Date2
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
Client, APIGateway(auth, rate limit, log, route), LB(distribute load to instances), Instances(containing docker images of services spinned up), DB (SQL for payment transactions as we need acid properties, mongo for movies, seats, user info etc, schema is flexible), cache (Redis for movie list), Kafka for order service, payment service, notification service - event driven architecture, maybe elastic search for top 10 frequently accessed movie , CDN for thumbnails, pictures, trailer, S3 for blob storage when owner uploads
Define the data model. Identify the main entities, their attributes, and relationships. Consider the choice of database type (SQL vs NoSQL) and justify your decision based on access patterns...
SQL - Payments so PaymentTable {paymentId, userId, bookingId, paymentMethod, paymentStatus}
NoSQL - User{userId, username, email, firstname, lastname, address/city, isOwner:Bool(No for user, Yes for owner, license (ifOwner) }, Movie {id, title, s3urlImage, s3urlTrailer, genre, duration, languages[], type(2D/3D)}, Seat {id, movie id (theatre id i guess }
seat hold mechanism: in the redis create a booking to hold , show_id , seatId, status as hold, ttl, when TTL dies it is marked as not booked, if not booked, freeing up for other users.
Now when payment fails also need to update not booked, on success case, right away the record status is set to booked.
In case of network error, if a hold is already created, it can be checked instead of creating same/similar one and resume from there.
DB needs to be sharded so it can handle scale and also instead of one write, it can do parallel writes, shard by show_id
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
Lets us discuss kafka, when order service is called, it is written to kafka topics, so payment service will call for lets say an external api to do the operation, here i could have used webhook but then it has to come back to orderservice, paymentservice, notification service, instead i used kafka so one event is consumed by multiple listeners reducing latency. Kafka is also persistant, so when something breaks due to network or any failures, the consumers would check their offset and resume working. we need consistency for payment so kafka is better choice. I introduced CDN cache because if an event is popular then it would be needed to be called again and again so to reduce load to call static content S3, CDN cache is used. Then i used elastic search, people usually look for trending movies like top 10, in such cases elasticsearch can give good throughput as it uses inverted indexes to compress multiple rows, making it faster.
Concurrency: when two users click a same link, here we cant do optimistic lock, we need to hold the seat so we do pessimistic lock, so only one user gets the lock. if user 2 also tries to request, the data is checked in redis to see if there is a hold before writing to seat table, if there is one then user2 shouldnt be allowed to proceed. If TTL(5min) expires then the booking is not made, lock can be released by checking if the TTL is already expired in redis