System requirements


Functional:

List functional requirements for the system (Ask the chat bot for hints if stuck.)...

  1. Users should be able to view the events.
  2. Users should be able to search for the events
  3. User s should be able to book tickets for the events.

Out of scope for now:

  1. Users should be able to view the booked tickets
  2. Admin or event coordinators should be able to add events
  3. Popular events have dynamic pricing


Non-Functional:

List non-functional requirements for the system...

  1. Highly available search and viewing events
  2. Highly consistent for booking events
  3. should have low latency
  4. system should be scalable, able to handle 10 M request for an event
  5. read heavy (100:1)

Out of scope:

  1. system should be fault tolerant
  2. secure transactions for payments




Capacity estimation

Estimate the scale of the system you are going to design...


  1. Assume users viewing/searching events per day = 1K per day


  1. Assume users purchasing the events per day = 1K per day
  2. No. of events scheduled per month = 10 events per month

Storage capacity

  1. Event info record size = 1KB
  2. 100 events per month = 1KB*10*365/30 = 12.5MB/year
  3. In 5 years = 1GB event storage in 5 years(storage = 12.5*5 )a(approx)
  4. Tickets info record size = 1KB
  5. Tickets stored per year = 1KB*1000*365 = 365 MB/year
  6. in 5 years approx 1GB tickets stored





API design

Define what APIs are expected from the system...



  1. View event API:
    1. GET /events/:eventId
  2. Search Event API:
    1. GET /events/search?keyword={keyword}&start={start_date}&end={end_date}
  3. Book tickets:
    1. POST /bookings/:eventId -> returns bookingId

pass:

{

"tickets":string[],

"paymentDetails: ...

}


Database design

Defining the system data model early on will clarify how data will flow among different components of the system. Also you could draw an ER diagram using the diagramming tool to enhance your design...


Event Database:

  1. PostgreSQL is used as we need to have ACID properties, we need to have relational database. If only storage is concerned and No ACID properties required, then NoSQL is used.
    1. Event:id, venueId, performerId, tickets[], name, description
    2. Venue: id, location, seatMap
    3. Performer: id
    4. Ticket: id, eventId, seat, price, status: available, booked,userId
    5. Booking: id, userId, tickets





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

Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...

  1. User should be able to view events:
    1. Client makes a REST GET request with the eventId.
    2. The API Gateway then forwards the request onto Event Service.
    3. The Event Service then queries the Event DB for the event, venue, performer info and returns to the client.

Users should be able to search events:

  1. Client makes the REST GET API with search parameters.
  2. The API Gateway authenticates the request and forward it to load balancer and then forward to Search Service.
  3. The Search service then queries the Event DB for the events matching the search parameters and returns them to clients.


Users should be able to book tickets:

  1. We add two new tables in DB- Booking and Tickets.
  2. Booking service will interface with Stripe for transaction and communicate with Booking and Tickets table to fetch, update or store relevant data.
  3. User is redirected to booking page for payments and book tickets.
  4. POST request is sent with selected ticket IDs.
  5. The booking server initiates transaction to check the availability of selected seats.
  6. Update status of selected tickets to "Booked".
  7. Create new booking record in the bookings table.



Detailed component design

Dig deeper into 2-3 components and explain in detail how they work. For example, how well does each component scale? Any relevant algorithm or data structure you like to use for a component? Also you could draw a diagram using the diagramming tool to enhance your design...



To improve user experience in booking -

  1. We need to have strong isolation and concurrency methods to avoid double booking for same seats.
  2. We can use concurrency method such as Optimistic Concurrency Control (OCC) when conflicts are rare and instead of locking it checks if data has been changed before committing.
  3. We can have distributed locking with (TTL) time to live using distributed system like Redis. It offers high availability and distributed locking mechanism. When user selects the tickets, it holds lock in redis with TTL, this TTL acts as automatic expiration time for the lock. If user completes the purchase within the time, the ticket status is changed to booked and lock in redis is manually released after TTL.
  4. If user abandons the purchase or TTL expires, then redis automatically releases the lock and ticket is available to users for booking.
  5. Scale Event Data
    1. by adding caching since heavy read and less frequency of update. This ensures high availability.
    2. Cache Invalidation Strategies and consistency - TTL , setyp database triggers to notify the caching system for updates in data like pricing, event dates etc.
    3. Load balancing - round robin or least connection

Ensure seat map is up to date.

1 SSE (server sent event) for real time updates to clients. It is unidirectional communication channel between server and client. It allows server to push data to clients without client having to request it.

This might be challenging in case of extremely popular events when available seats disapper in instant.

For extremely popular events, we can implement admin enabled virtual waiting queue system to manage user access during times of high demand.

when user requests to view the booking page, they are placed in virtual waiting queue.We establish a websocket connection with client and add users to queue using their unique websocket connection.


Trade offs/Tech choices

Explain any trade offs you have made and why you made certain tech choices...

  1. SQL vs NoSQL - as we need strong consistency, we go with SQL and since I am familiar with PostgreSQL, we opted it.
  2. Monolith vs Microservice - we opted microservice as to prevent single point of failure and each service can be scaled independently in future
  3. For faster lookups, we used cache (Redis) instead of hitting DB call. Ticket lock redis will store key value pair where key is ticket_id and value is user_id.
  4. Full text search engine like elasticsearch where each unique word is mapped to documents or records it appears in.




Failure scenarios/bottlenecks

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

  1. If Ticket Lock redis goes down, then user experience degraded. But we still don't have double booking, since our database will have OCC.
  2. Consistency issue between cache and database
  3. Long waiting time in queue.
  4. Keeping elastic search index and database in sync



Future improvements

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

  1. Load balancers to scale servers and databases horizontally.
  2. For long waiting time in queue, we can push updates to clients in real time, updating estimated waiting time.