Requirements


Functional Requirements:

Users should be able to view the events

Users should be able to search the events

Users should be able to book the tickets for the events.



Non-Functional Requirements:


  • Latency should be low for searching the events(<100ms)
  • Consistency should be prioritised when booking the events and availability should be prioritised when viewing the events.
  • Read ratio >> write ratio
  • Sharding should be handled for surge events


API Design

  • GET

/events/{term}?eventId=eventId?venue=venue?performer=performer

  • POST

/events/reserve

{eventId,

performer,

venue}

/events/confirm

-> ticketId

As for booking the tickets it will be always 2 endpoints one for reserving and another for confirming.For booking the events there should be 2 api's as one for reserving and another for booking.The reserving should lock the seat for 5 mins and within 5 mins if the transaction is not completed then close the window and mark the seat to available.


High-Level Design

The first functional requirement is user should be able to view the event so we will have our client which will send the request via the API Gateway and the request will go to event service which is responsible for adding the event , viewing the event which will fetch the details from the database.Currently we can use PostgreSQL or some SQL DB as our data structure will not change frequently and we will be using some joins between the DB.So currently for this usecase SQL db works fine.Now coming to next requirement user should be able to search the event.So we will use the query SELECT * from DB where type in [] AND name like "%term%". Now user should be able to book the tickets .So the requests of reserving the ticket and confirming the ticket will go to booking service.So from booking service we can open an endpoint for the payment which we can handle via stripe endpoint. So now we have handled all the functional requirements except the thing that how will we handle the requirement of currently the user should be able to view all the seats but we are not handling the scenario where if the user select(reserve ) a seat for payment then that seat shouldnt be visible to user.So we are making sure that this is handled via placing the reservedTimeStamp in the db so that when user want to look at the list of tickets available then the user can go to the list of tickets available and then look at the tickets details if tickets reserveTimeStamp is more than current time -5mins then move that back to available state.So we have to write our application code like that and it may cause an overhead in the application code so what we can do is we can place a cron job which will run for every 10mins and update the status looking at the timestamps but there is a con in this as the user has to wait until the cron job is updated then only the user can see the latest status.So instead of cron job we can place a distributed locked redis so we can set a TTL in the redis to get expired automatically after 5mins .So whenever we want to fetch the seatmap we can fetch the available seats and in the seats we will also check if there any tickets in reserved state via the ticket lock redis then update the latest available seats.

Here comes the end of functional requirements which is not perfect so we can make perfect by moving to the non functional requirements.


Detailed Component Design

So the first non functional requirement is latency should be low for read.Here for the search we are following a query and that query will be extremely slow as the wildcard matching is there.So what we can do is we can replace that by having an elastic search .So the elastic search uses inverted search so with the words like taylor or swift it maps and gives the list of events related to the term.So internally the elastic search uses BM25 ranking for performing the search and give the results in less time.We dont use the elastic search as our primary DB as it is not reliable and we will loose our primary properties of ACID and so what we want to do is update our Elastic search along with PostgreSQL but if we write our application code like that then there might be chances that our DB got updated but not elastic search or elastic search got updated but not DB so we can use the change data capture or CDC which will identify the changes in the DB and push those stream of changes to the Elastic search. So to reduce the read latency further we can use the elastic search inbuilt AWS Opensearch which will cache the frequently accessed data to the cache or we can use the redis in between and cache the frequently used keys and use the LRU as the eviction policy.But we can use the elastic search AWS Open search as to reduce the overhead of maintaining other cache.The other thing which we can do is place a CDN in between client and api gateway which will cache and fetch the results .But the problem with the CDN is the search currently had many parameters to consider so the search key may change frequently so the many of the cache become less useful as it wont be able to figure our which one is same.So it also add's more complexity and comes with more cost too.So we satisfied that non functional requirement and the other non functional requirement is about that consistency should be prioritised like when 2 users open the events displayed should be same like suppose if user opens to look at the tickets which are available and we gave the correct available seats for that moment but as user sits on that page for long the data will be stale so what we can do is do a long polling which will poll for 30seconds and update the latest available seats to the user and this works for 5mins but according to data user sits on this page for longer so what we can do is create a persistant connection like SSE and update the data accordigly.So now another functional requirement is handling events when taylor swift or other popular celebrity posts something then millions of people fight for limited seats it will be a bad user experience if the entire screen goes blank.So the admin can specify few events as special events or so where the requests will go to a virtual waiting queue where the redis will be used with priority queue so that the one first entered will be prioritised so this is our choke point.So now whatever request came we will redirect those to virtual waiting queue and say as your request is taken into consideration will let you know the availability in few mins or so.Now if we see other functional requirements it was that availability should be prioritise when viewing the events so we can redis to cache and fetch the results faster.This redis should be kept up to date .If any of the event is dismissed immediately the redis should also be updated to remove that cache entry.