Skip to content
intermediatePhase 50 · LLD Practice

Movie Ticket Booking

Design a movie booking system with seats, shows, and pricing.

2h
0 problems
Topic Progress0%

Requirements

Functional Requirements

1. Movie Management:
   - Add/update movies
   - Show times and schedules

2. Theater Management:
   - Multiple theaters/screens
   - Seat layout configuration

3. Booking:
   - Select movie, show, seats
   - Multiple seat selection
   - Apply discounts/coupons

4. Payment:
   - Multiple payment methods
   - Booking confirmation
   - Refund policy

5. Seat Management:
   - Real-time seat availability
   - Block seats during booking
   - Release on timeout

Core Entities

Movie, Show, Theater, Screen, Seat,
Booking, User, Payment, Coupon

Booking Flow

1. Browse movies
2. Select movie
3. Select show (date + time)
4. Select seats
5. Apply coupons
6. Make payment
7. Get confirmation

Seat Management

Seat Layout

┌──────────────────────────────────────────┐
│              SCREEN                       │
├──────────────────────────────────────────┤
│  Row A: [1] [2] [3] [4] [5] [6] [7] [8]│
│  Row B: [1] [2] [3] [4] [5] [6] [7] [8]│
│  Row C: [1] [2] [3] [4] [5] [6] [7] [8]│
│  Row D: [1] [2] [3] [4] [5] [6] [7] [8]│
├──────────────────────────────────────────┤
│  Legend: [✓] Available  [✗] Booked       │
│          [●] Blocked    [★] Premium      │
└──────────────────────────────────────────┘

Seat Class

public class Seat {
    private final String seatId;
    private final SeatType type;     // STANDARD, PREMIUM, RECLINER
    private final SeatStatus status; // AVAILABLE, BOOKED, BLOCKED, MAINTENANCE
    private final double price;
    
    public boolean isAvailable() {
        return status == SeatStatus.AVAILABLE;
    }
    
    public void block() {
        if (status == SeatStatus.AVAILABLE) {
            this.status = SeatStatus.BLOCKED;
        }
    }
    
    public void book() {
        if (status == SeatStatus.BLOCKED) {
            this.status = SeatStatus.BOOKED;
        }
    }
    
    public void release() {
        if (status == SeatStatus.BLOCKED) {
            this.status = SeatStatus.AVAILABLE;
        }
    }
}

SeatMap

public class SeatMap {
    private final Map<String, Seat> seats;
    private final int rows;
    private final int columns;
    
    public List<Seat> getAvailableSeats() {
        return seats.values().stream()
            .filter(Seat::isAvailable)
            .collect(Collectors.toList());
    }
    
    public boolean blockSeats(List<String> seatIds) {
        // Atomic blocking - all or nothing
        synchronized (this) {
            List<Seat> seatsToBlock = seatIds.stream()
                .map(seats::get)
                .collect(Collectors.toList());
            
            if (seatsToBlock.stream().allMatch(Seat::isAvailable)) {
                seatsToBlock.forEach(Seat::block);
                return true;
            }
            return false;
        }
    }
}

Seat Pricing

public class SeatPricing {
    public double calculatePrice(Seat seat, Show show) {
        double basePrice = seat.getPrice();
        
        // Apply time-based pricing
        if (show.isPeakTime()) {
            basePrice *= 1.2;
        }
        
        // Apply weekend pricing
        if (show.isWeekend()) {
            basePrice *= 1.3;
        }
        
        return basePrice;
    }
}

Booking Flow

Booking Service

public class BookingService {
    private final SeatMap seatMap;
    private final PaymentService paymentService;
    private final NotificationService notificationService;
    
    public Booking createBooking(User user, Show show, 
                                 List<String> seatIds) {
        // 1. Block seats (atomic)
        if (!seatMap.blockSeats(seatIds)) {
            throw new SeatsNotAvailableException();
        }
        
        // 2. Create booking with timeout
        Booking booking = new Booking(user, show, seatIds);
        booking.setTimeout(5 * 60 * 1000); // 5 minutes
        
        // 3. Start timeout timer
        scheduleTimeout(booking);
        
        return booking;
    }
    
    public void confirmBooking(Booking booking, Payment payment) {
        // 1. Process payment
        paymentService.process(payment);
        
        // 2. Book seats
        booking.getSeatIds().forEach(id -> seatMap.getSeat(id).book());
        
        // 3. Update booking status
        booking.setStatus(BookingStatus.CONFIRMED);
        
        // 4. Send confirmation
        notificationService.sendBookingConfirmation(booking);
    }
    
    private void scheduleTimeout(Booking booking) {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (booking.getStatus() == BookingStatus.PENDING) {
                    // Release blocked seats
                    booking.getSeatIds().forEach(
                        id -> seatMap.getSeat(id).release()
                    );
                    booking.setStatus(BookingStatus.EXPIRED);
                }
            }
        }, booking.getTimeout());
    }
}

Booking Class

public class Booking {
    private final String bookingId;
    private final User user;
    private final Show show;
    private final List<String> seatIds;
    private BookingStatus status;
    private final LocalDateTime createdAt;
    private double totalAmount;
    
    public enum BookingStatus {
        PENDING, CONFIRMED, CANCELLED, EXPIRED
    }
}

Payment Processing

public class PaymentService {
    public PaymentResult process(Booking booking, PaymentDetails details) {
        // 1. Validate payment details
        validatePayment(details);
        
        // 2. Calculate total
        double total = calculateTotal(booking);
        
        // 3. Process with payment provider
        return paymentProvider.charge(details, total);
    }
    
    private double calculateTotal(Booking booking) {
        SeatPricing pricing = new SeatPricing();
        return booking.getSeatIds().stream()
            .mapToDouble(id -> pricing.calculatePrice(
                seatMap.getSeat(id), booking.getShow()))
            .sum();
    }
}

Follow-ups

Follow-up Questions

1. How to handle concurrent seat selection?
   → Atomic seat blocking
   → Optimistic locking with version
   → Distributed locks for scalability

2. How to handle refunds?
   → Refund policy per show
   → Partial refunds for partial cancellation
   → Refund to original payment method

3. How to handle seat selection timeout?
   → Timer-based release
   → Block duration configuration
   → Notification before expiry

4. How to handle multiple shows at same time?
   → Independent seat maps per show
   → Shared theater management
   → Conflict detection

5. How to handle dynamic pricing?
   → Demand-based pricing
   → Early bird discounts
   → Group discounts

Design Patterns

Pattern Usage
Observer Seat availability updates
Strategy Pricing calculation
Factory Booking creation
State Booking status transitions
Singleton SeatMap management

Database Schema

movies (id, title, genre, duration)
theaters (id, name, location)
screens (id, theater_id, seat_config)
seats (id, screen_id, row, col, type, price)
shows (id, movie_id, screen_id, time, price)
bookings (id, user_id, show_id, status, total)
booking_seats (booking_id, seat_id)
payments (id, booking_id, amount, method, status)

Practice Problems

0/3solved
Design Movie Ticket Booking System

Design a scalable Movie Ticket Booking system. Cover high-level architecture, data model, and API design.

Solution
// Complete system design:
// - Functional + Non-functional requirements
// - Capacity estimation
// - Data model (SQL/NoSQL choice)
// - API endpoints
// - Component architecture
// - Scaling strategy
// - Monitoring & reliability
Movie Ticket Booking Scaling

How would you scale Movie Ticket Booking to handle 10x the current load? Identify bottlenecks and solutions.

Solution
// Scaling approach:
// 1. Load balancing
// 2. Database sharding/replication
// 3. Cache layer (Redis)
// 4. CDN for static assets
// 5. Async processing (queues)
// 6. Microservices decomposition
Movie Ticket Booking Failure Modes

Analyze potential failure modes for Movie Ticket Booking and design mitigation strategies.

Solution
// Failure mitigation:
// 1. Redundancy (multi-AZ)
// 2. Circuit breakers
// 3. Retry with backoff
// 4. Dead letter queues
// 5. Health checks
// 6. Graceful degradation

Quiz

1. What happens when a user selects seats but doesn't complete payment?

Question 1 options

2. How is concurrent seat booking handled?

Question 2 options

3. How is seat pricing calculated?

Question 3 options

4. What is the booking flow?

Question 4 options

5. How are refunds handled?

Question 5 options

Flashcards

Question

Booking flow steps?

Answer

1) Select movie, 2) Select show, 3) Select seats, 4) Block seats, 5) Apply coupons, 6) Pay, 7) Confirm.

Question

How is seat concurrency handled?

Answer

Atomic blocking: all seats blocked or none. Timeout releases blocked seats if payment not completed.

Question

Seat pricing formula?

Answer

Base price × peak time multiplier × weekend multiplier. Different seat types (standard, premium) have different base prices.

Question

What happens on booking timeout?

Answer

Blocked seats are released back to available. Booking status changes to EXPIRED. No charge to user.

Question

Key entity relationships?

Answer

Theater → Screens → Seats. Movie → Shows. Show has Seats. Booking links User, Show, Seats.

Revision Notes

Key Takeaways

  • 1.Seat blocking is atomic: all seats blocked or none
  • 2.Timeout releases blocked seats if payment isn't completed
  • 3.Seat pricing uses base price with time and weekend multipliers
  • 4.Booking status transitions: PENDING → CONFIRMED/CANCELLED/EXPIRED
  • 5.Concurrent booking requires atomic operations and locking

Interview Tips

  • Explain atomic seat blocking for concurrency
  • Show the complete booking flow with timeout mechanism
  • Discuss pricing strategy with multipliers
  • Mention refund policy and partial cancellation handling

Cheat Sheet

Movie Ticket Booking - Cheat Sheet

Core Entities:
Movie, Show, Theater, Screen, Seat, Booking, User, Payment

Booking Flow:

  1. Select movie → 2. Select show → 3. Select seats → 4. Block seats → 5. Apply coupons → 6. Pay → 7. Confirm

Seat Management:

  • Atomic blocking (all or nothing)
  • Timeout releases blocked seats
  • Status: Available → Blocked → Booked

Pricing:
Base Price × Peak Multiplier × Weekend Multiplier

Concurrency:

  • Atomic seat blocking
  • Optimistic locking
  • Timeout mechanism

Patterns:
Observer (availability), Strategy (pricing), State (booking status), Factory (creation)