System requirements


Functional:

user can view ticket for an event

user can view event

user can book a ticket for an event

user can search for a event


Non-Functional:

highly Consistency as one ticket can only be book and purchase by one user.

highly available, consistency >> availability

low latency for better user experience.

read > write

need to handle double booking scenarios


Capacity estimation

1 million users and DAU 50, 000. Assume 1% book ticket. 5000 booked ticket.

50, 000 DAU makes 10 queries daily 50 QPS.


100kb per event and 1000 event per day

10M which is nothing.



API design

GET v1/ticket={ticketId}

return ticket


GET v1/event={event}

return list of eventIDs


GET v1/search

parameter : artist, location, dateTime

return list of eventIDs


POST v1/book-{ticketID}

return status of booking 400s 200s


all above has to pass user information at JWT header




Database design

use SQL since ACID.


Ticket:

-ticketId

-price

-artists

-dateTime

-seats


Event:

-eventId

-time

-location

-artist


User

-userId



High-level design


write path: client request to API gateway(handle authentication, rate limiting, load balancing) , to booking service, booking result return to client and save to dababase.


booking service use 3rd party payment like paypal/stripe to process payment.


read path, client request to API gateway(handle authentication, rate limiting, load balancing), to query service, to database , then return result to client.




Request flows

write path: client request to API gateway(handle authentication, rate limiting, load balancing) , to booking service, booking result return to client and save to dababase.


read path, client request to API gateway(handle authentication, rate limiting, load balancing), to query service, to database , then return result to client.




Detailed component design

leveraging elastic search and inverted index for event search. use CDS capture data change - make string out of change of database and consume the string to elastic search.


To improve latency:

1, cache top search in elastic search.

2, use CDN



how to ensure consistency between database and cache? we could use 2 phased commit.



handle popular event: cache popular event.


sharding,

data is small, considering future events, we could shard by geolocation and eventid.





1, user double click

solution 1, handle at client side to grey out submit button. down side is client side may disable it.

solution 2, handle at server side using idempotent Key. when booking button clicked, service generate idempotent key associated with booking, and when booking service try to book, it check if idempotent key already in the system.


2, double booking issue - multiple user trying to book the same ticket at the same time.

solution 1, use lock, but lock has hard to scale even distributed lock and intruduce latency. hard to manage unlock time,

use redis cache feature LLT, once ticket booked by one user, it will be added to LLT cache. When other people trying to book, it will first check if it in LLT cache, if its not in TTL cache then it's available to book. After certain amount time, if use did not payment, it got removed from LLT cache.








Failure scenarios/bottlenecks

redundancy

if server fail, secondary replaces it. if master database fail, one of the slave become master.



Future improvements

1, we could use long pulling to handle handle seat availability realtime for better user experience

2, implement chock point- virtual waiting queue for situation of million people fighting for a popular ticket like superbow or taylor swift ticket.