One of the best systems for learning Low-Level Design is BookMyShow.
Because at first glance, it looks simple:
User selects movie
→ chooses seats
→ makes payment
→ booking gets confirmed
But internally, this system forces us to solve some very important design problems:
- seat consistency
- concurrent booking
- lifecycle management
- state transitions
- ownership boundaries
- workflow orchestration
Which makes it an excellent domain modeling exercise.
Step 1 — Understand the Core Business Flow
Before thinking about classes, understand the workflow first.
Simplified booking flow:
User selects show
→ selects seats
→ seats get locked
→ payment happens
→ booking gets confirmed
Now ask carefully:
Which objects own these responsibilities?
That question drives the design.
Step 2 — Identify Core Entities
We start with business objects that:
- have identity
- evolve over time
- require tracking
Movie
- movieId
- title
- duration
- language
Movie has business identity.
Entity ✅
Theater
Tracks:
- location
- screens
- configuration
Entity ✅
Show
Very important Entity.
Why?
Because Show controls:
- timing
- seat availability
- booking state
- pricing context
Show becomes central to consistency.
Booking
Booking has:
- bookingId
- lifecycle
- payment relationship
- cancellation state
Entity ✅
Step 3 — Identify Value Objects
Now separate descriptive values.
SeatNumber
SeatNumber("A12")
We care about:
- the value itself not
- independent lifecycle
Value Object ✅
Money
Money(₹450)
Again:
- defined by value
- no identity
Value Object ✅
TimeRange
Represents:
- start time
- end time
Also a Value Object.
Step 4 — Identify Critical Invariants
This is where real system design begins.
Ask:
“What business rules must NEVER break?”
Most Important Invariant
Same seat cannot be booked twice for the same show.
This single rule shapes most of the system design.
Other invariants:
- cancelled bookings should release seats
- payment must happen before confirmation
- locked seats should expire eventually
- invalid seat transitions must not occur
Step 5 — Find the Correct Aggregate Boundary
This is where many beginner designs fail.
A common mistake is making Booking responsible for seats.
But think carefully.
Who actually owns seat consistency?
The answer is:
Show.
Show Aggregate
Show Aggregate
├── Show (Root)
├── SeatAvailability
├── Pricing
└── Timing
The Show Aggregate becomes responsible for:
- locking seats
- confirming seats
- releasing seats
- protecting booking consistency
This is extremely important.
Why Booking Should NOT Control Seats
Imagine this design:
Booking → directly marks seats booked
Now multiple bookings can race against each other.
Consistency becomes fragile.
Instead:
Booking asks Show to reserve seats
Now consistency remains centralized.
That is good aggregate design.
Step 6 — Model Seat State Transitions
Seats evolve through states.
Example:
AVAILABLE
→ LOCKED
→ BOOKED
Or:
LOCKED
→ AVAILABLE
if payment fails or timeout occurs.
These transitions must remain controlled.
Example Domain Logic
class Show {
void lockSeats(List<SeatNumber> seats) {
if(!areAvailable(seats)) {
throw new SeatUnavailableException();
}
markLocked(seats);
}
}
Notice:
- Show protects consistency
- invalid transitions are blocked
- business rules stay centralized
Step 7 — Separate Workflow From Domain Logic
Now comes orchestration.
Booking flow involves:
- seat locking
- payment
- notifications
- booking confirmation
This coordination belongs in Services.
BookingService
class BookingService {
void createBooking(User user, Show show, Seats seats) {
show.lockSeats(seats);
paymentService.process();
booking.confirm();
notificationService.send();
}
}
Service coordinates workflow.
Show protects consistency.
That separation is critical.
Step 8 — Think Beyond the Happy Path
Strong LLD always considers failures.
Example:
- payment fails
- user abandons flow
- seat lock expires
- duplicate requests happen
Now state management becomes even more important.
Weak systems fail under these situations.
Strong systems protect consistency despite failures.
Final Domain Model
Entities
- Movie
- Theater
- Show
- Booking
Value Objects
- SeatNumber
- Money
- TimeRange
Aggregate
- Show Aggregate
Invariants
- no double booking
- valid seat lifecycle
Services
- BookingService
- PaymentService
- NotificationService
The Most Important Insight
BookMyShow is not fundamentally a “movie booking system”.
At its core, it is actually:
a consistency management system.
The hardest problem is not:
- rendering UI
- exposing APIs
- storing records
The hardest problem is:
- protecting valid seat state under concurrent usage.
And that is exactly why domain modeling matters in real Low-Level Design.
Because strong systems are built by identifying:
- ownership
- consistency boundaries
- lifecycle control
- responsibility separation
before writing large amounts of code.
Top comments (0)