Architecture & LLD

Booking Framework

BOOKING & RESERVATION · LLD FAMILY

Booking & Reservation

01

Every booking system is the same five parts

Whatever the domain, the vocabulary is identical. Separate the inventory (the resources) from the reservation (a hold on one), and treat concurrency as a first-class concern, not an afterthought. Map the four nouns of your specific problem onto these five and the design writes itself.

📦
Inventory
The finite set of bookable resources — seats, rooms, spots, copies. Each is free or held.
🎫
Reservation
A hold on one resource for a window of time. Has its own lifecycle (held → confirmed → …).
🔎
Availability
Search free resources matching criteria (date range, type, capacity).
💳
Pricing
Compute cost on confirm/checkout — flat, per-hour, dynamic. A pluggable Strategy.
🔒
Concurrency
The hard part: two requests must never grab the same resource. Atomic check-and-set.
GenericParking LotBookMyShowLibraryHotel
Inventoryparking spotsseats in a showbook copiesrooms
Reservationticketbookingloanreservation
Availabilityfree spot by typefree seatsavailable copyfree room for dates
Pricingfee by durationseat-class pricelate finenightly rate
Time windowentry → exitshow timeborrow → duecheck-in → out
02

The reservation lifecycle

A reservation is a little state machine. The crucial state is HELD — a temporary hold that must expire if not confirmed, so abandoned carts don't lock inventory forever. On confirm it becomes a real booking; on timeout or cancel it releases the resource back to the pool.

SEARCHING
→hold
HELD
TTL expiry
→pay
CONFIRMED
→arrive
CHECKED_IN
→done
COMPLETED
→timeout
EXPIRED / CANCELLED
→ release resource
WHY A SEPARATE “HELD” STATE?

Without it you either confirm instantly (no time to pay) or never reserve (everyone races for the same seat at checkout). A short-lived hold with a TTL gives the user time to pay while guaranteeing the resource is returned if they vanish. This is the single most important idea in the family.

03

The core challenge — never double-book

The interview is this problem. Two requests read “seat available”, both write “booked”, and now two people own seat 14F. The fix is to make check-and-set atomic — wrap find-then-hold in a lock (pessimistic) or use a conditional/compare-and-swap write (optimistic). Watch the race with the lock off, then on:

NO LOCK (race condition)
Request A
reads seat → AVAILABLE
1 seat
Request B
reads seat → AVAILABLE
Both read “available” before either writes — the classic lost-update race.
Pessimistic (lock)
Lock the resource (or row), check, set, unlock. Simple and correct; can limit throughput under heavy contention. Good default for an LLD answer.
Fine-grained (atomic claim)
Give each resource its own atomic flag and compareAndSet(free → held); only the winning thread proceeds, the loser scans on. Lets unrelated bookings run in parallel.
04

Design decisions that matter

01

Hold first, confirm later

Never jump straight to BOOKED. Reserve a short-lived HELD with a TTL so the user can pay, and a background sweep (or lazy check) releases expired holds.
02

Make the booking step atomic

The whole find-free → mark-held sequence is one critical section. A lock per resource (or an optimistic conditional write) is what prevents double-booking.
03

Pricing is a Strategy

Flat, per-hour, per-night, surge, seat-class — keep these out of the manager behind a PricingStrategy so new schemes don't touch core logic.
04

Model time explicitly

Reservations occupy a [from, to) interval. Availability = “no overlapping reservation for this resource”. Overlap checks are the heart of hotels and meeting rooms.
05

The design patterns you'll reuse

Reservation lifecycleState
HELD → CONFIRMED → … → COMPLETED / EXPIRED, each permitting different actions.
PricingStrategy
Swap flat / hourly / dynamic pricing without touching the manager.
Spot / seat allocationStrategy
Nearest, cheapest, best-fit — pluggable allocation policy.
The single managerSingleton / Facade
One entry point coordinating inventory, search and pricing.
Notify on confirmObserver
Email/SMS subscribers react when a reservation changes state.
06

Common pitfalls

Non-atomic check-and-set
Reading “free” then writing “booked” in two steps lets two requests win the same resource. Lock or use a conditional write.
Holds that never expire
Abandoned carts permanently sink inventory. Every HELD needs a TTL and a release path.
Pricing baked into the manager
if-chains for every fee scheme. Extract a PricingStrategy.
Forgetting the time dimension
Treating a resource as simply free/taken instead of free over an interval — breaks hotels and scheduling.
No idempotency on confirm
A retried “confirm” charges twice. Key the operation by reservation id.
07

The problems in this family

Each keeps inventory + hold/confirm/release + atomic booking — only the resource, the time model and the pricing change.

🅿️
Parking LotMEDIUM · START HERE
Spots as typed inventory, ticket on entry, fee Strategy on exit. The canonical machine-coding problem.
🎬
Movie Ticket BookingHARD
Seat hold with TTL + concurrency — the double-booking problem at its sharpest.
📚
Library ManagementMEDIUM
Copies as inventory, loans with due dates, fines as pricing.
🏨
Hotel ReservationMEDIUM
Rooms booked over date ranges — interval-overlap availability.
📅
Meeting Room SchedulerMEDIUM
Rooms over time slots, conflict detection, next-free-slot search.