DEV Community

Cover image for Concert Ticket Booking Platform: A Highly Scalable and Reliable Design
abhilaksh-arora
abhilaksh-arora

Posted on

Concert Ticket Booking Platform: A Highly Scalable and Reliable Design

Problem Statement:

Design a highly scalable and reliable concert ticket booking platform for a live event where:

  • 10,000 tickets are available across multiple zones/arenas (e.g., General Admission, VIP, Millionaire Pit).
  • Tickets go live at exactly 10:00 AM, with approximately 10 million users accessing the platform simultaneously.
  • Users should experience real-time updates on their queue position and ticket availability.
  • The system must prevent double booking of seats, handle cancellations, and reintroduce canceled tickets to the pool.
  • Users have 10 minutes to complete their booking; otherwise, their session expires.

Assumptions:

To make the design adaptable to various scenarios, we consider two primary assumptions:

Assumption 1: Specific Seat Numbers

Each seat is uniquely identified (e.g., 1A, 1B, etc.). Users select specific seats during booking. This model is common in arenas, theaters, and venues with assigned seating.

Assumption 2: General Pool of Seats

Tickets are sold as part of a general pool without specific seat assignments. Users book tickets based on availability in a zone, but seating is on a first-come, first-served basis. This model is suitable for standing areas, open parks, or general admission zones.


High-Level Design (HLD):

System Requirements:

Functional Requirements:

  • Users can view ticket availability in real time.
  • The system queues users when tickets go live.
  • Users can reserve tickets for 10 minutes before completing payment.
  • Canceled or expired reservations return to availability.
  • Users can see their position in the queue.

Non-Functional Requirements:

  • Scalability: Handle 10 million concurrent users.
  • Reliability: Ensure no double bookings or data inconsistencies.
  • Low Latency: Real-time updates on availability and queue positions.
  • Fault Tolerance: Handle partial system failures gracefully.
  • Consistency: Maintain consistent ticket inventory across multiple services.

Architecture Overview:

  • Frontend:
    • Displays real-time ticket availability.
    • Shows queue position and updates dynamically using WebSockets.
  • Backend:
    • Orchestrates ticket reservation, payment, and inventory management.
    • Provides APIs for frontend interactions.
  • Queue Management:
    • Manages user queues for fairness and prevents system overload.
    • Redis lists are used to maintain queue order.
  • Database:
    • Stores persistent ticket information, including seat details and statuses (AVAILABLE, RESERVED, BOOKED).
    • PostgreSQL for strong consistency and relational data modeling.
  • Caching Layer:
    • Redis for real-time ticket inventory management and reservation TTLs. Message Queue:
    • RabbitMQ/Kafka for handling asynchronous operations like notifications and inventory updates.

Component Breakdown:

  • Frontend:
    • Displays live updates on ticket availability and user queue positions.
    • Communicates with the backend using REST APIs and WebSockets.
  • Load Balancer:
    • Distributes traffic across multiple backend servers to ensure scalability.
    • Can use AWS Elastic Load Balancer (ELB) or Nginx.
  • Queue Management:
    • Implements user queuing using BullMQ.
    • Using a Redis sorted set to track user positions in the queue.
    • A consumer processes users in FIFO order.
    • Once dequeued, a user gets 10 minutes (TTL) in Redis to select tickets.
  • Inventory Management:
    • Tracks ticket availability in realtime.
    • Stored in Redis for high-speed access with a fallback to PostgreSQL.
  • Session Management:
    • Redis handles user sessions with a TTL of 10 minutes.
    • Reserved tickets are automatically released upon session expiration.
    • Once a user selects tickets or their session expires, remove them from the queue and the Redis sorted set.
  • Database:
    • PostgreSQL for durable storage of ticket data.
    • Schema:
 tickets (id, arena_id, seat_id, status, user_id, reserved_at)  
 arenas (id, name, total_capacity)  
 users (id, name, email)  
Enter fullscreen mode Exit fullscreen mode
  • Messaging and Notifications:
    • RabbitMQ for notifying users about queue updates and broadcasting real-time availability changes to WebSockets.
  • Payment Gateway Integration:
    • Integrates with payment services like Stripe.
    • Ensures tickets remain reserved until payment is confirmed or the session expires.

**

Low-Level Design (LLD) for Concert Ticket Booking System

**

Detailed Components and Interactions

BullMQ Queue:

Purpose: To manage user queues fairly, track positions efficiently, and prevent system overload.

Queue:

  • Primary Queue: Handles user queuing and job processing.
  • FIFO Order: Users are processed in the order they enter the queue.
  • Redis Backing: BullMQ leverages Redis for persistence.

Redis Sorted Set:

  • Key: arena::queue
  • Purpose: Tracks user positions in the queue for real-time updates.
  • Operations:
    • ZADD: Add a user with a score representing their position.
    • ZRANK: Get a user’s position in the queue.
    • ZREM: Remove a user from the queue when dequeued.
    • ZCARD: Get the total number of users in the queue.

Workflow:

Adding Users:

  • BullMQ: queue.add() to enqueue users.
  • Redis: ZADD to track the user's position by score (e.g., timestamp or incrementing counter).

Processing Users:

  • BullMQ: queue.process() to dequeue and handle users.
  • Redis: ZREM to remove the processed user from the sorted set.

Tracking Position:

  • Use ZRANK to retrieve the current position of a user.
  • Use ZCARD for the total queue size.

Advantages:

  • BullMQ: Simplifies job processing with robust retry mechanisms and concurrency control.
  • Redis Sorted Set: Efficient position tracking with O(log N) operations, ideal for real-time updates.

Inventory Management

Purpose: To track and update ticket availability in real time.

Redis Structures:

Specific Seats:

  • Key: arena::seats
  • Value: Hash map of seat IDs to statuses.
  • Example:
    • HSET arena:VIP:seats 1A AVAILABLE
    • HSET arena:VIP:seats 1B RESERVED

General Pool:

  • Key: arena::available_tickets
  • Value: Integer count of available tickets.
  • Example:
    • SET arena:general:available_tickets 5000

Workflow:

  • When a user selects a ticket, the system updates its status in Redis (e.g., HSET for specific seats, DECR for general pools).
  • For confirmed bookings, the status is updated to BOOKED.
  • For canceled or expired reservations, the system reverts the status to AVAILABLE.

Session Management

Purpose: To manage user sessions and enforce the 10-minute reservation limit.

Redis Keys:

  • Key: session:
  • Value: JSON object with session details.
  • TTL: 10 minutes (automatically expires).

Workflow:

  • On reservation, create a session in Redis with a 10-minute TTL.
  • If the user completes payment within the TTL, finalize the booking.
  • If the session expires, release the tickets back to the pool.

Ticket Booking Process

Steps:

User Selects Ticket(s):

  • API: POST /tickets/reserve
  • Request Body:
  {
    "user_id": "123",
    "zone_id": "VIP",
    "seats": ["1A", "1B"]
  }
Enter fullscreen mode Exit fullscreen mode
  • Actions:
    • Check availability in Redis.
    • Mark tickets as RESERVED in Redis.
    • Start a session with a 10-minute TTL.

User Completes Payment:

  • API: POST /tickets/book
  • Request Body:
  {
    "user_id": "123",
    "zone_id": "VIP",
    "seats": ["1A", "1B"],
    "payment_id": "pay_456"
  }
Enter fullscreen mode Exit fullscreen mode
  • Actions:
    • Verify payment.
    • Update ticket status to BOOKED in Redis and PostgreSQL.
    • In the case of the general pool, decrement the ticket count.
    • Delete the user's session information from Redis to free up resources.
    • Notify other users via WebSocket about the change in seat availability.

User Cancels Reservation:

  • API: POST /tickets/cancel
  • Actions:
    • Update ticket status to AVAILABLE in Redis and PostgreSQL.

Real-Time Updates

WebSocket Events:

queue.update:

  • Triggered when a user’s queue position changes.
  • Payload:
  {
    "user_id": "123",
    "position": 42
  }
Enter fullscreen mode Exit fullscreen mode

availability.update:

  • Triggered when ticket inventory changes.
  • Payload:
  {
    "zone_id": "VIP",
    "available_tickets": 95
  }
Enter fullscreen mode Exit fullscreen mode

Database Transactions

Reserve Ticket:

BEGIN;
SELECT * FROM tickets WHERE id = '1A' AND status = 'AVAILABLE' FOR UPDATE;
UPDATE tickets SET status = 'RESERVED', reserved_at = NOW() WHERE id = '1A';
COMMIT;
Enter fullscreen mode Exit fullscreen mode

Book Ticket:

BEGIN;
UPDATE tickets SET status = 'BOOKED' WHERE id = '1A';
INSERT INTO payments (id, user_id, amount) VALUES ('pay_456', '123', 100);
COMMIT;
Enter fullscreen mode Exit fullscreen mode

Cancel Ticket:

BEGIN;
UPDATE tickets SET status = 'AVAILABLE', reserved_at = NULL WHERE id = '1A';
COMMIT;
Enter fullscreen mode Exit fullscreen mode

Messaging and Notifications

Use RabbitMQ for:

  • Broadcasting availability updates to WebSocket services.
  • Notifying users of reservation expirations.

Summary:

When the concert tickets go live at 10:00 AM, users are placed in a queue managed by Redis, ensuring fairness and avoiding system overload. The frontend displays real-time availability and queue position using WebSockets. When a user reaches their turn, they select tickets, which are temporarily marked as RESERVED in Redis with a 10-minute TTL to prevent double booking. If the user completes payment within the session, the tickets are marked BOOKED in the database and removed from Redis reservations. If the session expires or the user cancels, the tickets return to the AVAILABLE pool, and updates are pushed to the next users in the queue. This flow ensures high concurrency handling, real-time updates, and seamless booking without collisions.

Why This Approach Works

  • Real-Time Updates: Redis ensures fast updates and notifications for concurrent users.
  • Durability: PostgreSQL acts as the source of truth to ensure data is not lost in case of Redis failures.
  • Concurrency: Redis's atomic operations (MULTI and WATCH) prevent double booking.
  • Scalability: WebSocket-based updates ensure seamless communication with millions of users.

This detailed LLD ensures a robust, scalable, and user-friendly platform for concert ticket booking, addressing the needs for both specific seat assignments and general admission models.


Top comments (0)