Compile Ready
All low level design problems
Low Level Design/Intermediate/Core Systems

Design a Hotel Management System

Rooms, rates, reservations, check-in/out, and housekeeping — a broad domain-modelling exercise.

Intermediate 55m interview 17m read Medium frequency Popularity 76
State Strategy Factory Method Observer Amazon Airbnb Oracle

Problem Statement

Design the object model for a hotel management system that can search available rooms over a requested stay, create reservations, move them through check-in and check-out, price the stay, and produce an invoice.

The heart of the problem is not CRUD. It is the date-range invariant: a room is unavailable for a request if any active reservation for that room overlaps the requested [check-in, check-out) interval. The design should make that rule explicit and reusable across search, booking, cancellation, and billing.

Business context

Hotel Management appears in Amazon, Airbnb, and Oracle style interviews because it combines booking, inventory, state transitions, and pricing in one familiar domain. A good answer separates room inventory from reservation lifecycle, keeps date logic deterministic, and gives the business seams for taxes, seasonal rates, housekeeping, channel managers, and no-show handling.

Interviewers are looking for whether the candidate can protect a scarce resource across time. A design that only checks whether a room is currently empty misses the real problem: future reservations must block overlapping future stays too.

Functional Requirements

  • Maintain hotel rooms with room number, floor, type, capacity, and operational status.

  • Support room types such as Standard, Deluxe, and Suite with base nightly rates and guest capacity.

  • Search available rooms for a room type, guest count, and check-in/check-out date range.

  • Create a reservation only when the chosen room has no active overlapping reservation.

  • Move a reservation through Reserved, CheckedIn, CheckedOut, Cancelled, and NoShow states with valid transitions only.

  • Allow cancellation and no-show marking before check-in so blocked inventory can be released.

  • Generate an invoice on check-out using a pluggable pricing strategy and optional extra charges.

  • Notify observers such as housekeeping and availability boards when room status changes.

Non-Functional Requirements

Date-range correctness

Availability must use half-open intervals and the overlap rule requestStart < existingEnd && requestEnd > existingStart. Adjacent stays where one check-out equals the next check-in are allowed.

Lifecycle safety

Reservation transitions must be centralized so a cancelled reservation cannot check in and a checked-out reservation cannot be billed twice through the same flow.

Extensibility

New pricing plans, room creation rules, and observers should be additive classes rather than edits inside the reservation flow.

Low-latency search

The interview implementation can scan in memory, but it must make the hot path clear enough to replace with indexed inventory later.

Auditability

Invoices should capture the reservation id, room charge, extras, tax, total, and issue time so customer disputes can be explained.

Requirement Clarification

QAre check-in and check-out dates inclusive?

Use a half-open interval: check-in is inclusive and check-out is exclusive. A stay from Aug 1 to Aug 4 occupies the nights of Aug 1, Aug 2, and Aug 3, and another guest may check in on Aug 4.

QShould cancelled and no-show reservations block availability?

No. They remain in history but stop blocking inventory. Only Reserved and CheckedIn reservations block a room for overlap checks.

QDo we allocate a specific room at reservation time?

Yes for the base design. The service searches matching rooms and binds the first available room to the reservation. A later extension can support room-type-only inventory pools.

QDo we need payment gateway integration?

No for the core LLD. The system produces an invoice. Payment collection is a boundary adapter that can consume the invoice total.

QHow is housekeeping represented?

Room status changes are observable. Check-out moves the room to Cleaning, an observer can dispatch housekeeping, and the room becomes searchable again only after it is marked Available.

UML Class Diagram

Rendering diagram…
The service is the aggregate boundary, but it delegates overlap checks to **Reservation**, search policy to **SearchService**, lifecycle rules to state objects, pricing to **PricingStrategy**, and room creation to **RoomFactory**.

Sequence Diagram

Rendering diagram…
Reservation creation depends on overlap search; check-in and check-out are state transitions that also drive room status observers.

Entity Identification

Room

Represents a physical room. It owns operational status, knows its room type, and notifies observers whenever status changes.

roomNumbertypefloorstatusobservers

RoomType

Defines capacity and base nightly rate for Standard, Deluxe, and Suite rooms. Search uses capacity, pricing uses the rate.

baseNightlyRateCentsmaxGuests

Reservation

Binds a guest, room, date range, guest count, and current state. It owns the overlap predicate and delegates valid transitions to its state object.

idguestNameroomcheckInDatecheckOutDatestate

ReservationState

State pattern seam for reservation lifecycle. Concrete states decide whether inventory is blocked and which transitions are legal.

ReservedStateCheckedInStateCheckedOutStateCancelledStateNoShowState

SearchService

Filters candidate rooms by type, guest capacity, room status, and active overlapping reservations using one date-range rule.

findAvailableRoomsisAvailable

PricingStrategy

Calculates invoice totals from nights, room type rate, extra charges, and tax. Seasonal or channel-specific pricing can replace the default strategy.

createInvoice

Invoice

Immutable billing result produced at check-out with room charge, extras, tax, total, reservation id, and issue timestamp.

reservationIdroomChargeCentsextraChargeCentstaxCentstotalCents

HotelService

Application service and aggregate boundary. It owns collections, creates rooms and reservations, coordinates lifecycle calls, and returns invoices.

roomsreservationssearchServicepricingStrategyroomFactory

RoomObserver

Observer interface for secondary reactions to room status changes, such as dispatching housekeeping or updating an availability board.

onStatusChanged

Design Patterns Used

State

ReservationState keeps lifecycle rules out of service code. Reserved permits check-in, cancellation, and no-show; CheckedIn permits check-out; terminal states reject further transitions.

Strategy

PricingStrategy isolates rate calculation and invoice creation. The check-out flow does not know whether pricing is standard, seasonal, member-discounted, or channel-specific.

Factory Method

RoomFactory centralizes room creation so validation, default status, room-number policy, and future room subclasses are not scattered across service methods.

Observer

RoomObserver lets housekeeping and availability boards react to room status changes without coupling those concerns to Room or HotelService.

Step-by-Step Design

  1. 1Define the date-range invariant first

    Use half-open stays and one overlap predicate everywhere. This allows back-to-back reservations and prevents the classic bug where checking current room status ignores future bookings.

    public boolean overlaps(LocalDate start, LocalDate end) {
        validateDateRange(start, end);
        return blocksInventory()
            && start.isBefore(checkOutDate)
            && end.isAfter(checkInDate);
    }
  2. 2Separate room type from room status

    RoomType captures stable commercial facts like rate and capacity. RoomStatus captures operational facts like Available, Occupied, Cleaning, and Maintenance.

  3. 3Put lifecycle behavior behind state objects

    The reservation exposes checkIn, checkOut, cancel, and markNoShow, but the current state decides what each call means. Illegal transitions fail immediately.

    final class ReservedState implements ReservationState {
        public void checkIn(Reservation reservation) {
            reservation.transitionTo(new CheckedInState());
            reservation.getRoom().markOccupied();
        }
    }
  4. 4Search by filtering rooms against active reservations

    SearchService first filters by room type, capacity, and operational status. It then rejects any room with an active reservation whose date range overlaps the request.

  5. 5Generate invoices through a strategy

    Check-out transitions the reservation, moves the room to Cleaning, and asks the injected pricing strategy for the invoice. The service coordinates; it does not hard-code rate math.

    public Invoice checkOut(String reservationId, List<Charge> extras) {
        Reservation reservation = getReservation(reservationId);
        reservation.checkOut();
        return pricingStrategy.createInvoice(reservation, extras);
    }
  6. 6Notify housekeeping and availability as observers

    Room status changes are local events. Observers subscribe to rooms and update secondary views without the domain model knowing those consumers exist.

Complete Java Implementation

Loading…

Explanation of Every Class

Room

Physical inventory unit. It stores room number, type, floor, and operational status, and fires observer callbacks when status changes. Search rejects rooms that are Cleaning or under Maintenance.

RoomType

Enum for stable commercial configuration: base nightly rate and maximum guest capacity. This avoids scattering rates and capacity checks across search and billing.

Reservation

Reservation owns the date range, guest binding, selected room, and state. Its overlaps method is the single source of truth for date-range availability.

PricingStrategy

Pricing seam plus the default implementation and invoice data model. StandardPricingStrategy multiplies nights by room rate, adds extras, applies tax, and returns an immutable Invoice.

SearchService

Availability query service. It filters by room type, capacity, status, and active overlapping reservations. It also contains sample observers for housekeeping and availability counts.

HotelService

Application boundary. It stores rooms and reservations, uses the factory to add rooms, delegates search to SearchService, delegates billing to PricingStrategy, and triggers reservation lifecycle methods.

Main

Small executable scenario showing search, reservation creation, overlap behavior, check-in, check-out, invoice generation, and housekeeping-driven availability restoration.

Dry Run

Sample input

Rooms: 201 Deluxe, 202 Deluxe. Existing none. Guest asks for Deluxe, 2 guests, Aug 1 to Aug 4. Then another guest searches Aug 3 to Aug 5 and Aug 4 to Aug 6.

StepRequestOverlap checkRoom statusReservation stateOutcome
1Search Deluxe Aug 1 to Aug 4No active reservations201 Available, 202 AvailableNoneBoth rooms returned
2Reserve Ava in 201 Aug 1 to Aug 4No overlap, create R1201 AvailableR1 Reserved201 is blocked for overlapping future stays
3Search Deluxe Aug 3 to Aug 5Aug 3 < Aug 4 and Aug 5 > Aug 1201 Available, 202 AvailableR1 Reserved201 rejected, 202 returned
4Search Deluxe Aug 4 to Aug 6Start equals R1 check-out, so no overlap201 Available, 202 AvailableR1 Reserved201 and 202 returned
5Check in and check out R1Historical reservation no longer blocks201 CleaningR1 CheckedOutInvoice = 3 nights plus extras plus tax
6Housekeeping marks 201 availableNo active overlap201 AvailableR1 CheckedOut201 can appear in future search again

The important row is step 3: even though room 201 is operationally Available before check-in, the future reservation blocks an overlapping request. Step 4 proves adjacent stays are legal under half-open intervals.

Complexity Analysis

OperationTimeSpaceNote
search available roomsO(R × B)O(R)R rooms and B reservations in the in-memory implementation. Each room may scan reservations for overlap.
reserveO(R × B)O(1)Delegates to search, then creates one reservation and stores it by id.
checkIn / cancel / markNoShowO(1)O(1)Map lookup plus a state transition; observer notifications are proportional to subscribers on room status changes.
checkOut and invoiceO(E + O)O(E)E extra charges and O room observers. Night count is constant-time date arithmetic.
single overlap checkO(1)O(1)Two date comparisons after validating the range.

The scan is acceptable for an interview model. Production search would index by room type and date, or precompute nightly inventory buckets, but the same half-open overlap rule remains the correctness contract.

Extensibility

Seasonal and channel pricing

Add another PricingStrategy that reads rate calendars, promo codes, loyalty tiers, or OTA channel markups. HotelService.checkOut does not change.

Room features

Add amenities such as ocean view, smoking preference, accessibility, or connecting rooms as filters on Room or as a separate RoomFeature set used by SearchService.

Room-type inventory pools

Instead of binding a physical room at booking time, reserve capacity at room-type level and assign a room on check-in. This improves operations but shifts overlap checks to inventory counters.

External integrations

Observers or adapters can publish availability updates to channel managers, send housekeeping tasks, or push invoices to accounting without changing the domain classes.

Alternative Designs

Nightly inventory buckets

Track remaining count per room type per night, decrementing all nights in the requested range when a reservation is created.

Tradeoffs

Search becomes fast for type-level availability, but assigning a specific room later needs a second placement step and careful rollback across multiple nights.

Repository and specification pattern

Move room and reservation lookup into repositories, and express filters as specifications such as RoomTypeMatches and NoOverlapForRange.

Tradeoffs

Better for persistence-heavy systems, but verbose for a machine-coding interview unless the interviewer asks for database boundaries.

Workflow engine for reservation lifecycle

Represent lifecycle transitions in a configurable workflow table instead of state classes.

Tradeoffs

Useful for enterprise policy changes, but the State pattern is clearer and safer for an interview-sized domain model.

Common Mistakes

  • ×

    Checking only RoomStatus.Available and forgetting future active reservations, which allows double booking.

  • ×

    Using inclusive end dates so a guest checking out on Aug 4 blocks another guest checking in on Aug 4.

  • ×

    Letting Cancelled or NoShow reservations continue to block search results.

  • ×

    Putting lifecycle transitions in nested service conditionals instead of a State pattern, making illegal transitions easy to miss.

  • ×

    Hard-coding room rates and tax in HotelService rather than a pricing strategy.

  • ×

    Marking a room Available immediately on check-out and skipping the Cleaning state and housekeeping workflow.

  • ×

    Creating an invoice before the reservation successfully transitions to CheckedOut.

Follow-up Interview Questions

QHow would you prevent two users from reserving the last room concurrently?

Wrap search plus reservation creation in a transaction or a lock on the room/date inventory. In a database design, use a uniqueness constraint or row locks over room and date-range inventory rows.

QHow would you support modifying reservation dates?

Validate the new range with the same overlap predicate while excluding the reservation being modified. Apply the change only if the new range has no active conflict.

QHow do you price weekend or holiday rates?

Implement a pricing strategy that iterates each night, looks up a rate calendar for that date and room type, then adds extras and tax before returning an invoice.

QWhere should payment processing live?

Outside the core model. The hotel domain creates invoices; a payment adapter charges the guest and records payment status against the invoice or reservation.

QHow would you support overbooking?

Introduce an inventory policy per room type that allows reserved count to exceed physical count by a configured buffer. Keep this out of Reservation.overlaps and put it in a higher-level allocation policy.

Production Considerations

Persistence and transactions

Store rooms, reservations, invoices, and state transitions durably. Reservation creation should be transactional with conflict detection to avoid double booking under concurrency.

Time zones and hotel calendars

Hotel stays use local property dates, not arbitrary instants. Keep property time zone and local check-in/check-out rules explicit.

Audit trail

Record who changed a reservation, previous state, next state, invoice inputs, and pricing strategy version. Hospitality disputes often depend on historical policy.

Operational reliability

Housekeeping, channel manager sync, email, and accounting should be asynchronous with retry and idempotency because those integrations fail independently of booking.

Search performance

Large hotels or multi-property systems need indexes by property, room type, and date range. The in-memory scan becomes an indexed availability query or cached inventory calendar.

What Interviewers Look For

  • Did the candidate state half-open date ranges and implement the correct overlap condition?

  • Can they explain which reservation states block inventory and which do not?

  • Is pricing behind an interface rather than mixed into check-out orchestration?

  • Do observers represent side effects without coupling housekeeping to the room entity?

  • Can the design evolve from a single hotel in memory to persisted, concurrent, multi-property inventory?

Quiz

0/5 answered

  1. 1.Which condition correctly detects overlap for half-open hotel stays?

  2. 2.Which reservation states should normally block inventory?

  3. 3.Why is pricing modeled as **PricingStrategy**?

  4. 4.What should happen when a checked-in guest checks out?

  5. 5.What does the Observer pattern decouple in this design?

Practice Variants

Add rate calendars

Intermediate

Implement a pricing strategy that charges different rates per night based on weekday, weekend, holiday, and seasonal demand.

Support reservation modification

Intermediate

Allow changing dates, room type, and guest count while preventing overlap with other active reservations for the same room.

Multi-property search

Advanced

Add Hotel or Property as a top-level aggregate and search availability across city, property, room type, and date range.

Flashcards

Cheat Sheet

Core entities: Room, RoomType, Reservation, ReservationState, SearchService, PricingStrategy, Invoice, HotelService, RoomObserver.

Overlap rule: use half-open stays. A request conflicts when requestStart < existingEnd && requestEnd > existingStart for the same room and an active reservation.

States: Reserved can check in, cancel, or no-show. CheckedIn can check out. CheckedOut, Cancelled, and NoShow are terminal and do not block inventory.

Patterns: State for reservation lifecycle, Strategy for pricing, Factory Method for room creation, Observer for housekeeping and availability updates.

Flow: search rooms → reject overlapping active reservations → create Reserved reservation → check in marks room Occupied → check out marks room Cleaning and creates invoice → housekeeping marks Available.

Complexity: simple search is O(R×B); overlap check is O(1); check-in and cancellation are O(1); check-out is O(extras + observers).

References