Bird
Raised Fist0

Design a Movie Ticket Booking System - Seats, Concurrency Lock, Expiry, Payment

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
🏗️
Design a Movie Ticket Booking System - Seats, Concurrency Lock, Expiry, Payment
Design a concurrent movie ticket booking system with seat locking, expiry, and payment integration
mediumBooking and Reservation SystemsFreq: high
Prerequisites:ConcurrencyOOP DesignJava synchronizationThread safetyDesign Patterns
⚙️
Functional Requirements
  • Allow customers to view available seats for a show
  • Lock selected seats for a limited time to prevent double booking
  • Automatically release seat locks after expiry if payment not completed
  • Process payment and confirm booking atomically
  • Support concurrent booking requests without race conditions
  • Allow cancellation and refund processing
  • Maintain seat status with thread-safe updates
👤
Use Cases
  • Search movies and showtimes
  • Select seats for a show
  • Lock seats temporarily during booking
  • Handle seat lock expiry and release
  • Process payment for booked seats
  • Confirm booking and generate ticket
  • Cancel booking and release seats
🧑‍💻
Actors
  • Customer
  • Payment Gateway
  • Theater System
  • Admin
❓
Clarifying Questions to Ask
  • How many concurrent booking requests (threads) are expected per show?
  • What is the seat lock expiry duration and can it be extended?
  • Is dynamic pricing or seat category pricing required?
  • What happens if payment fails after seat lock?
  • Are partial seat bookings allowed (e.g., group seats)?
  • How to handle network failures during booking confirmation?
Out of Scope
✗ Movie catalog management
✗ User authentication and authorization
✗ Detailed payment gateway integration
✗ UI/UX design
⚡
QPS Calculation
read qps5000
write qps1000
rationaleAssuming peak 1000 concurrent booking requests per show with 5x read to write ratio for seat availability.
🖥️
Server Estimate
app servers10
db servers3
cache servers2
rationaleBased on QPS and data volume, with horizontal scaling and caching.
🔢
Enumerations
enum SeatStatus
AVAILABLE | LOCKED | BOOKED
Represents seat lifecycle states; enum prevents typo bugs and enables exhaustive switch statements for seat state transitions.
enum PaymentStatus
PENDING | SUCCESS | FAILED
Defines payment outcome states; using enum ensures type safety and clear payment flow control.
enum LockExpiryReason
TIMEOUT | CANCELLED | CONFIRMED
Enumerates reasons for seat lock expiry to handle different unlock scenarios explicitly.
📦
Seat
4 fields
private final String seatIdprivate volatile SeatStatus statusprivate volatile String lockedByBookingIdprivate volatile long lockExpiryTimestamp
Represents a single seat in a theater show with thread-safe status updates and lock management.
public synchronized boolean lockSeat(String bookingId, long expiryTimestamp)Atomically locks the seat if AVAILABLE, sets lock owner and expiry timestamp.
public synchronized void unlockSeat(LockExpiryReason reason)Releases the seat lock and updates status based on expiry reason.
public synchronized boolean bookSeat(String bookingId)Marks the seat as BOOKED if currently locked by the same bookingId.
public synchronized boolean isAvailable()Checks if the seat is AVAILABLE for locking.
📦
Show
2 fields
private final String showIdprivate final Map<String, Seat> seats
Represents a movie show with a collection of seats; manages seat lookup and availability.
public Seat getSeat(String seatId)Returns the Seat object for given seatId.
public List<Seat> getAvailableSeats()Returns a list of seats currently AVAILABLE.
📦
Booking
5 fields
private final String bookingIdprivate final String showIdprivate final List<String> seatIdsprivate volatile PaymentStatus paymentStatusprivate volatile boolean isConfirmed
Represents a booking transaction with seat selections and payment status.
public synchronized boolean confirmBooking()Marks booking as confirmed if paymentStatus is SUCCESS.
public synchronized void cancelBooking()Cancels booking and triggers seat unlock.
public synchronized void updatePaymentStatus(PaymentStatus status)Updates payment status atomically.
📦
PaymentProcessor
1 fields
private final String paymentGatewayId
Handles payment processing and updates booking payment status.
public PaymentStatus processPayment(String bookingId, double amount)Processes payment synchronously and returns payment status.
📦
SeatLockExpiryManager
1 fields
private final ScheduledExecutorService scheduler
Manages seat lock expiry tasks and releases locks after timeout.
public void scheduleLockExpiry(Seat seat, long expiryTimestamp)Schedules a task to unlock seat after expiryTimestamp.
🔗
Relationships
Show◆──►Seat[1..*]
compositionSeat lifecycle bound to Show; seats cannot exist independently
Booking──►Seat[1..*]
associationBooking references seats but seats exist independently
Booking──►PaymentProcessor[1]
associationBooking uses PaymentProcessor but does not own it
SeatLockExpiryManager──►Seat[1]
associationManages expiry for seats but does not own them
🗄️
Shows
PK: showId
showId STRINGseatId STRINGstatus STRINGlockOwner STRINGlockExpiryTimestamp BIGINT
Stores seat status per show for quick availability lookup and locking.
🗄️
Bookings
PK: bookingId
bookingId STRINGshowId STRINGseatId STRINGpaymentStatus STRINGisConfirmed BOOLEAN
Stores booking details with seat references and payment status.
🔌
GET /shows/{showId}/seats
Request
{
  "showId": "string"
}
Response
{
  "seats": [
    {
      "seatId": "string",
      "status": "AVAILABLE|LOCKED|BOOKED"
    }
  ]
}
Returns seat availability for a given show.
🔌
POST /bookings
Request
{
  "showId": "string",
  "seatIds": [
    "string"
  ],
  "paymentDetails": "object"
}
Response
{
  "bookingId": "string",
  "status": "PENDING|SUCCESS|FAILED"
}
Creates a booking with seat locks and initiates payment.
🔌
POST /bookings/{bookingId}/cancel
Request
{
  "bookingId": "string"
}
Response
{
  "status": "CANCELLED"
}
Cancels a booking and releases locked seats.

Practice

(1/5)
1. In designing the vending machine's product selection module, should Product be modeled as an abstract class or an interface? Consider that products have shared state like price and inventory count, but different behaviors like dispense() and getDescription().
easy
A. Abstract class, because it allows sharing common state and default behavior implementations among products.
B. Abstract class, because it enforces immutability of product instances.
C. Interface, because Java interfaces can now have default methods to share code and state.
D. Interface, because all products only share behavior signatures without any shared state.

Solution

  1. Step 1: Analyze shared state and behavior

    Products share common state like price and inventory count, which requires fields and possibly default implementations.
  2. Step 2: Choose between interface and abstract class

    Abstract classes can hold state and provide default method implementations, while interfaces cannot hold instance state (only constants).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Abstract class supports shared state and behavior [check]
Hint: Abstract class holds state; interface only behavior signatures [check]
Common Mistakes:
2. In designing a Vehicle abstraction, should it be an abstract class or an interface if it needs to hold common state like speed and fuelLevel? Why?
easy
A. Abstract class, because it can hold shared state and provide common behavior implementations.
B. Interface, because it enforces method signatures without implementation or state, which is better for flexibility.
C. Interface, because it allows multiple inheritance and can hold default state variables.
D. Abstract class, because it forces subclasses to implement all methods without providing any default behavior.

Solution

  1. Step 1: Identify need for shared state

    Since speed and fuelLevel are common state variables, the abstraction must hold state.
  2. Step 2: Choose between abstract class and interface

    Interfaces cannot hold instance state (prior to Java 8 default methods, and even then no instance fields). Abstract classes can hold state and provide common behavior implementations.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Shared state -> abstract class, not interface [check]
Hint: State needs abstract class; interfaces can't hold instance variables [check]
Common Mistakes:
3. In a multi-threaded Chess game server, without synchronizing the makeMove() method, which exact sequence of thread interleaving causes two players to move simultaneously, violating turn order?
medium
A. Thread 1 reads current player as White, moves piece; Thread 2 reads current player as Black, moves piece simultaneously.
B. Thread 1 checks if it's White's turn -> true, context switch; Thread 2 checks if it's White's turn -> true; both proceed to move.
C. Thread 1 locks board, moves piece; Thread 2 waits but proceeds after unlock.
D. Thread 1 updates board state; Thread 2 reads stale board state but waits for turn.

Solution

  1. Step 1: Identify the check-then-act race condition

    Both threads read the turn state before either updates it, causing both to believe it's their turn.
  2. Step 2: Trace thread interleaving

    Thread 1 checks turn -> true, context switch before move; Thread 2 checks turn -> true, both move simultaneously, violating turn order.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap allows double move without synchronization [check]
Hint: Check turn then act without lock -> race condition [check]
Common Mistakes:
4. In the Airline Reservation System, if the reserveSeat() method is not synchronized, which exact sequence of thread interleaving causes double-booking of the same seat?
medium
A. Thread 1 and Thread 2 both fail to read seat status due to visibility issues, causing booking failure.
B. Thread 1 reads seat as available, Thread 2 reads seat as unavailable, both proceed to book.
C. Thread 1 locks seat, Thread 2 waits; Thread 1 releases lock after booking.
D. Thread 1 checks seat availability -> true, context switch before booking; Thread 2 checks availability -> true, both book seat.

Solution

  1. Step 1: Identify the check-then-act race condition

    Without synchronization, Thread 1 reads seat as available but is preempted before booking; Thread 2 also reads available and proceeds.
  2. Step 2: Both threads book the same seat concurrently

    Because no lock or atomic operation protects the check-and-book sequence, double-booking occurs.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Check-then-act gap without synchronization -> double-booking [check]
Hint: Check seat available -> context switch -> both book [check]
Common Mistakes:
5. ElectricCar plugins require ChargingSpot support in the plugin architecture. What is the minimum change to support this without modifying existing classes?
hard
A. Add charging support methods directly into the Plugin interface and implement them in all plugins.
B. Modify Vehicle class to add charging logic and update all existing plugin classes to handle ElectricCar.
C. Create a new ElectricCarPlugin class that duplicates Vehicle and Spot logic with charging support.
D. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar extending Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP; existing classes unchanged.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and new subclass ElectricCar extends Vehicle allows extension without changing existing code.
  2. Step 2: Update compatibility map to include new types without altering existing plugin or vehicle classes

    This preserves OCP and avoids class explosion or god-class logic.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Extend enums and subclass; update compatibility map; no existing class changes [check]
Hint: Extend enums + subclass + map update = minimal change [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard