System requirements


Functional:

User should be able to:

  • View movie details
  • View movie available tickets
  • Select seats
  • Hold seats for 10 minutes
  • Buy movie ticket
  • One ticket must only be belonged to one person


Non-Functional:

  • Scalability:
    • Adding more movies should not impact performance
    • Handle more users
  • Availability
    • For movie details, it must be available but can be stale if any update
    • For available seat, the available seat selections or remain number of ticket must be available but can be stale if any real-time recent update.
  • Reliability
    • No same ticket seat can be booked by 2+ users
    • Within 10 mins from when user book the seat ticket until process the payment, no other user can place the same seat.
  • Fault
    • Server processing payment is down
    • Server processing database for ticket is down.



Capacity estimation


  • 1M user can checkout concurrently
  • 100 movies on display at any given time





API design


GET /GetMovieDetail/api/v0/{movie_id}


GET /GetListOfMovie/api/v0/


GET /GetTheaterDetail/api/v0/{theater_id}

Request:

  • Header:
    • AuthorizationToken: string
  • Payload:
    • theater_id: string

Response:

  • Payload:
    • name: string
    • address: string


GET /GetAvailableSeat/api/v0/{movie_id}/{theater_id}

Request:

  • Header:
    • AuthorizationToken: string
  • Payload:
    • theater_id: string
    • movie_id: string

Response:

  • Payload:
    • available_seat: [string]



POST /HoldSeat/api/v0/{movie_id}

Request:

  • Header:
    • AuthorizationToken: string
  • Payload:
    • movie_id: string
    • theater_id: string
    • selected_seat: [string]

Response

  • Header:
    • Status: string
  • Payload
    • hold_end_time: UTC string
    • event_id: string
    • selected_seat: [string]
    • price: number


POST /SubmitPayment/api/v0/{event_id}


Request:

  • Header:
    • AuthorizationToken: string
    • Type: application/json
  • Payload:
    • event_id: string
    • paymentInfo:

Response

  • Header:
    • Status: string




Database design


Movie_tbl:

  • movie_id: string
  • title:
  • details
  • Length of movie


Theater_tbl:

  • theater_id: string
  • Address:
  • Info:


Theater_room_tbl:

  • room_id: string
  • room_name: string
  • all_seats: [seat_id]


Available_seat:

  • seat_id: string
  • event_id: string
  • status: string (empty, booked, hold)


Theater_Movie_relation:

  • Event_id: (key) string
  • Movie_theater_id: (sort_key) concat(movie_id, theater_id)
  • movie_time: UTC string


user_info_tbl:

  • user_id: string
  • payment_info: string


Available_seat_elastic_Cache: Hold the status of entries in Available_seat table

  • seat_id: string
  • event_id: string
  • status: string (empty, booked, hold)







High-level design


Client:

  • Web or mobile clients
  • Ticketing desks (application)


API Gateway:

  • Request will first reach API gateway. This will take care of authentication and authorization of the request. It will introduce rate limiter which apply blocking blacklist IPs and reduce constant rate with leaky bucket algorithm


Load Balancer:

  • It will first apply Session optimizer to select servers that has been serving customer request. 10 mins timeout would end up remove these relationship.
  • If a new request, Least Utilized optimizer would be used to select available


Booking Request SQS:

  • Holding the request so each lambda downstream can pick up perform async process workflow


Booking Request Dead-letter-queue DLQ:

  • Failed request end up in this DLQ for backoff retries


Async workflow:

  • Handling booking request


Locking:

  • Elastic Cache to keep hold of booking ticket by updating on each entry of {seat_id, event_id, status} in the cache
  • status can be {booked, hold, empty}


TaskScheduler

  • task scheduler to keep track of ending time of each event to flush the cache since we don't want people to book finished-played movie


Payment:

  • After payment complete, an SNS topic will get the notification and invoke async lambda to update the Available_seat_elastic_Cache and Available_seat table







Request flows






Detailed component design





Trade offs/Tech choices

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






Failure scenarios/bottlenecks

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






Future improvements

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