Design a Ticket Booking Site Like Ticketmaster

With Ex-Meta Staff Engineer & co-founder of hellointerview.com

Evan King
7 min readNov 27, 2024

Understanding the Problem

🎟️ What is Ticketmaster? Ticketmaster is an online platform that allows users to purchase tickets for concerts, sports events, theater, and other live entertainment.

Functional Requirements

Core Requirements

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

Below the line (out of scope):

  • Users should be able to view their booked events
  • Admins or event coordinators should be able to add events
  • Popular events should have dynamic pricing

Non-Functional Requirements

Core Requirements

  1. The system should prioritize availability for searching & viewing events, but should prioritize consistency for booking events (no double booking)
  2. The system should be scalable and able to handle high throughput in the form of popular events (10 million users, one event)
  3. The system should have low latency search (< 500ms)
  4. The system is read heavy, and thus needs to be able to support high read throughput (100:1)

Below the line (out of scope):

  • The system should protect user data and adhere to GDPR
  • The system should be fault tolerant
  • The system should provide secure transactions for purchases
  • The system should be well tested and easy to deploy (CI/CD pipelines)
  • The system should have regular backups

Here is how the requirements might look on the whiteboard:

Adding features that are out of scope is a “nice to have”. It shows product thinking and gives your interviewer a chance to help you reprioritize based on what they want to see in the interview. That said, it’s very much a nice to have. If additional features are not coming to you quickly, don’t waste your time and move on.

Planning the Approach

Before you move on to designing the system, it’s important to start by taking a moment to plan your strategy. Fortunately, for these common user-facing product-style questions, the plan should be straightforward: build your design up sequentially, going one by one through your functional requirements. This will help you stay focused and ensure you don’t get lost in the weeds as you go. Once you’ve satisfied the functional requirements, you’ll rely on your non-functional requirements to guide you through the deep dives.

Defining the Core Entities

I like to begin with a broad overview of the primary entities. At this stage, it is not necessary to know every specific column or detail. We will focus on the intricacies, such as columns and fields, later when we have a clearer grasp. Initially, establishing these key entities will guide our thought process and lay a solid foundation as we progress towards defining the API.

To satisfy our key functional requirements, we’ll need the following entities:

  1. Event: This entity stores essential information about an event, including details like the date, description, type, and the performer or team involved. It acts as the central point of information for each unique event.
  2. User: Represents the individual interacting with the system. Needs no further explanation.
  3. Performer: Represents the individual or group performing or participating in the event. Key attributes for this entity include the performer’s name, a brief description, and potentially links to their work or profiles. (Note: this could be artist, company, collective — a lot of different entities. The choice of “performer” is intending to be general enough to cover all possible groups)
  4. Venue: Represents the physical location where an event is held. Each venue entity includes details such as address, capacity, and a specific seat map, providing a layout of seating arrangements unique to the venue.
  5. Ticket: Contains information related to individual tickets for events. This includes attributes such as the associated event ID, seat details (like section, row, and seat number), pricing, and status (available or sold).
  6. Booking: Records the details of a user’s ticket purchase. It typically includes the user ID, a list of ticket IDs being booked, total price, and booking status (such as in-progress or confirmed). This entity is key in managing the transaction aspect of the ticket purchasing process.

In the actual interview, this can be as simple as a short list like this. Just make sure you talk through the entities with your interviewer to ensure you are on the same page.

As you move onto the design, your objective is simple: create a system that meets all functional and non-functional requirements. To do this, I recommend you start by satisfying the functional requirements and then layer in the non-functional requirements afterward. This will help you stay focused and ensure you don’t get lost in the weeds as you go.

API or System Interface

The API for viewing events is straightforward. We create a simple GET endpoint that takes in an eventId and return the details of that event.

GET /events/:eventId -> Event & Venue & Performer & Ticket[]
- tickets are to render the seat map on the Client

In most instances, your interviewer will be able to read between the lines of your core entities and the requirement we’re satisfying to understand the data returned by the API. They will either tell you or you can ask them if they’d like you to go into additional detail but be cautious about being over-verbose — you have a lot of ground to cover and enumerating the fields in the Event object may not be the best use of your time!

Next, for search, we just need a single GET endpoint that takes in a set of search parameters and returns a list of events that match those parameters.

GET /events/search?keyword={keyword}&start={start_date}&end={end_date}&pageSize={page_size}&page={page_number} -> Event[]

When it comes to purchasing/booking a ticket, we have a post endpoint that takes the list of tickets and payment payment details and returns a bookingId.

Later in the design, we’ll evolve this into two separate endpoints — one for reserving a ticket and one for confirming a purchase, but this is a good starting point.

POST /bookings/:eventId -> bookingId
{
"ticketIds": string[],
"paymentDetails": ...
}

It’s ok to have simple APIs from the start that you evolve as your design progresses. As always, just communicate, “Here is a simple API to start, but as we get into the design, we’ll likely need to evolve this to handle more complex scenarios.”

High-Level Design

1) Users should be able to view events

When a user navigates to www.yourticketmaster.com/event/:eventId they should see details about that event. Crucially, this should include a seatmap showing seat availability. The page will also display the event’s name, along with a description. Key information such as the location (including venue details), event dates, and facts about the performers or teams involved could be outlined.

We start by laying out the core components for communicating between the client and our microservices. We add our first service, “Event Service,” which connects to a database that stores the event, venue, and performer data outlined in the Core Entities above. This service will handle the reading/viewing of events

  1. Clients: Users will interact with the system through the clients website or app. All client requests will be routed to the system’s backend through an API Gateway.
  2. API Gateway: This serves as an entry point for clients to access the different microservices of the system. It’s primarily responsible for routing requests to the appropriate services but can also be configured to handle cross-cutting concerns like authentication, rate limiting, and logging.
  3. Event Service: Our first microservice is responsible for handling view API requests by fetching the necessary event, venue, and performer information from the database and returning the results to the client.
  4. Events DB: Stores tables for events, performers, and venues.

Let’s walk through exactly what happens when a user makes a request to www.yourticketmaster.com/event/:eventId to view an event.

  1. The client makes a REST GET request with the eventId
  2. The API gateway then forwards the request onto our Event Service.
  3. The Event Service then queries the Events DB for the event, venue, and performer information and returns it to the client.

2) Users should be able to search for events

Sweet, we now have the core functionality in place to view an event! But how are users supposed to find events in the first place? When users first open your site, they expect to be able to search for upcoming events. This search will be parameterized based on any combination of keywords, artists/teams, location, date, or event type.

Let’s start with the most basic thing you could do — we’ll create a simple service which accepts search queries. This service will connect your DB and query it by filtering for the fields in the API request. This has issues, but it’s a good starting point. We will dig into better options in the deep dives below.

When a user makes a search request, it’s straightforward:

  1. The client makes a REST GET request with the search parameters
  2. Our load balancer accepts the request and routes it to the API gateway with the fewest current connections.
  3. The API gateway then, after handling basic authentication and rate limiting, forward the request onto our Search Service.
  4. The Search Service then queries the Events DB for the events matching the search parameters and returns them to the client.

Don’t stop here! Read the rest of the design here.

(Don’t worry, it’s 100% free)

--

--

No responses yet