System requirements
Functional:
- user can book tickets for events
- user can view event details
- user can search for events
out of scope:
- authentication
- manage booked tickets
- manage events
Non-Functional:
- strong consistency for booking, i.e. no double booking
- high availability for search & view event
- < 200ms latency for search
- scalable to handle traffic surges for popular events
- read >> write
out of scope
- GDPR
- payment path security
- fault tolerance
- CI/CD
Capacity estimation
- 10k venues
- 1 event per venue per day
- 1MB image per event
- 10GB storage per day
- 4TB storage per year
- 500 seats/tickets per event
- 5M tickets per day
- 1KB per ticket
- 5GB for tickets per day
- 2TB storage per day
- 5M tickets per day
- assume all purchased
- 100K sec per day
- 50 write per s
- 100:1 read:write ratio
- 5K read per s
API design
GET /api/v1/events/:event_id => Event, Venue, Performer, Date, Tickets
GET /api/v1/events/search?{location}&{start_date}&{end_date}&{page_size}&{page_cursor}&{venue}&{performer}
=> Partial<Ticket>[]
POST /api/v1/events/:event_id/ticket/:ticket_id/hold
=> {
expiration_time,
}
POST /api/v1/booking
body {
ticketIds[],
}
=> booking_id
POST /api/v1/booking/:booking_id/confirm
body {
booking_id
paymentDetails
}
=> confirmation_id
Database design
User
- id
- name
- ...
Ticket
- id
- seat_number
- status: ['available','booked', 'payment_processing']
- hold_user_id
- hold_expiry
- event_id
- price
Event
- id
- name
- venue_id
- s3_image_url
- details
- performer
- start_time
- end_time
Venue
- id
- name
- location
- ...
Performer
- id
- name
- ...
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
- user is on event page
- user selects available tickets
- each selection calls POST /ticket/:ticket_id/hold
- Booking Service stores hold in Redis with TTL {ticketId: True}
- user clicks "checkout"
- this posts selected ticket ids to create booking
- user is prompted to enter payment details
- user "confirms"
- payment details submitted to booking service
- booking checks for lock & updates tickets to payment_pending status
- booking service validates payment details
- tickets and bookings are updated
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...
Trade offs/Tech choices
- Use of Redis for Ticket Lock increases performance but is less durable
- alternative is to store lock in ticket DB but much less performant
Failure scenarios/bottlenecks
- redis can crash, then locks will be lost and other users will be able to buy "locked" tickets"
Future improvements
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?