Preview — Pro guide
You are seeing a portion of this guide. Sign in and upgrade to unlock the full article, quizzes, and interview answers.
Sections
Related Guides
Hotel Booking System — LLD Deep Dive
Low-Level Design
Concurrency Patterns: Thread Safety, Producer-Consumer, Read-Write Lock & Thread Pool
Low-Level Design
Design Patterns for LLD Interviews
Low-Level Design
SOLID Principles in Practice
Low-Level Design
LLD Interview Framework & Walkthrough
Low-Level Design
Movie & Event Ticket Booking — LLD (Seat Map, Holds, Concurrency)
Object-oriented design for BookMyShow-style ticketing: venue seat graph, per-show instance inventory, time-boxed seat holds, and TOCTOU-safe booking. Covers pricing strategies, idempotent checkout, and extension to best-available search without an HLD detour.
What Interviewers Are Actually Testing
This problem is inventory reservation under contention, not drawing Seat rectangles on a whiteboard. Strong candidates separate three clocks: the show (a performance instance in time), the seat (a durable asset in a venue), and the hold (a short-lived lease so payment can run). The trap is implementing is_seat_free() and book() as two steps without an atomic path — the same race you fix in hotel booking, but with explicit seat labels and a visible UX countdown. A staff-level answer names at-least-once payment webhooks, idempotent booking confirmation, and why best-available search belongs behind a pluggable SeatSelectionStrategy interface.
Clarifying Questions — Before You Draw a Seat Grid
Fixed seating (each seat is unique) vs general admission?
Fixed seating: each Seat has row/column, state is per (show, seat_id). General admission: model CapacityBucket and decrement a counter; selection strategy collapses to FIFO. Most interviews mean fixed — confirm early.
Single venue or many screens under one tenant?
Single Venue is enough for the core LLD. Multi-venue chains add a CinemaChain root and venue-scoped inventory; out-of-band search is deferred but name it.
How are prices determined?
Flat per seat, per section (Orchestra, Balcony), or dynamic (surge by demand). Drives a PricingEngine and SeatingSection with its own Money base price — not a get_price() on Seat.
Hold duration and what happens on expiry?
Typical: ~5–10 minutes on the client timer (exact seconds are a product choice). Hold transitions EXPIRED and releases the seat; background sweeper reclaims lost holds. Ask whether partial payment retries are in scope (usually: idempotent confirm endpoint).
Pick-your-seat vs best-available auto assignment?
Pick-a-seat: user selects specific seat_id values. Best-available: BestAvailableSelector returns the first k non-overlapping seats per policy (adjacent, center bias). This must be a Strategy — the graph layout algorithm should not be hardcoded in BookingService.
Concurrent requests per show scale?
If millions fight for a stadium onsale, the LLD object model stays the same; the interviewer may expect you to name DB SELECT ... FOR UPDATE on (show_id, seat_id) or optimistic retries. Say it explicitly even if the code uses one lock.