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
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 & reliabilityHow 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 decompositionAnalyze 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 degradationQuiz
1. What happens when a user selects seats but doesn't complete payment?
2. How is concurrent seat booking handled?
3. How is seat pricing calculated?
4. What is the booking flow?
5. How are refunds handled?
Flashcards
Question
Booking flow steps?
Click to reveal answer
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?
Click to reveal answer
Answer
Atomic blocking: all seats blocked or none. Timeout releases blocked seats if payment not completed.
Question
Seat pricing formula?
Click to reveal answer
Answer
Base price × peak time multiplier × weekend multiplier. Different seat types (standard, premium) have different base prices.
Question
What happens on booking timeout?
Click to reveal answer
Answer
Blocked seats are released back to available. Booking status changes to EXPIRED. No charge to user.
Question
Key entity relationships?
Click to reveal answer
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:
- 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)