Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • About
  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

👥10,106visitors

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
HomeLearnSystem DesignLow-Level Design & Design PatternsMachine Coding Exercises
✓ FreeAdvanced· 7 min read

Hotel Reservation System

Hotel/Room/RoomType/Reservation classes, efficient date-range availability search via interval representation, and overbooking as a deliberate business rule rather than a bug.

Published September 23, 2026


Hotel Reservation System

Core classes

class Hotel { List<Room> rooms; }
class RoomType { String name; double basePrice; int capacity; } // Standard, Deluxe, Suite
class Room { String number; RoomType type; }
class Reservation { Room room; Guest guest; LocalDate checkIn; LocalDate checkOut; }

Advertisement

Modeling availability search across a date range efficiently

The naive approach — for each candidate room, scan every existing reservation checking for date overlap — is O(rooms * reservations per room) per search, which gets slow as reservation history grows. The better representation: for each room, keep reservations in a structure that supports fast interval overlap queries.

class Room {
    private final TreeMap<LocalDate, Reservation> reservationsByCheckIn = new TreeMap<>(); // sorted by check-in date

    boolean isAvailable(LocalDate checkIn, LocalDate checkOut) {
        // Find the reservation with the latest check-in date that's still <= requested checkOut
        Map.Entry<LocalDate, Reservation> candidate = reservationsByCheckIn.floorEntry(checkOut.minusDays(1));
        if (candidate == null) return true; // no reservation starts before the requested window ends
        Reservation r = candidate.getValue();
        return !r.getCheckOut().isAfter(checkIn); // the closest-preceding reservation must fully end before our check-in
    }
}

A TreeMap sorted by check-in date turns "is there any overlapping reservation" into a single floorEntry() lookup (O(log n)) that finds the most relevant candidate directly, rather than scanning every reservation for this room. This is the same underlying idea as TreeMap & LinkedHashMap's NavigableMap range-query methods, applied to interval scheduling specifically.

Overbooking: a deliberate business rule, not a bug

Real hotels (and airlines — see Airline Booking / Seat Selection System) deliberately overbook by a small, statistically-modeled margin, betting that historical no-show rates will absorb the overage. This is worth naming explicitly in a design discussion: a strict "never allow more reservations than physical rooms" constraint is the simpler design, but a real hotel booking system needs an explicit overbooking policy as a configurable business parameter (e.g. "allow up to 5% overbooking on RoomType") — and critically, needs a defined contingency process for the rare case where overbooking doesn't get absorbed by no-shows (walking a guest to a partner hotel, compensation). Treating overbooking as an unambiguous bug to eliminate, rather than asking whether it's an intentional business lever, is a common miss in this exact prompt.

Availability by room type, not by room

Guests book a room type for a date range ("a Deluxe for 12–15 March"). The specific room is usually assigned at check-in. That makes availability a counting problem per type and per night, which is simpler and faster than scanning individual rooms:

class RoomTypeInventory {
    private final RoomType type;
    private final int totalRooms;
    private final Map<LocalDate, Integer> booked = new HashMap<>();   // nights already sold
    private final double overbookingFactor;                            // e.g. 1.05 = sell up to 5% over

    RoomTypeInventory(RoomType type, int totalRooms, double overbookingFactor) {
        this.type = type; this.totalRooms = totalRooms; this.overbookingFactor = overbookingFactor;
    }

    private int sellable() { return (int) Math.floor(totalRooms * overbookingFactor); }

    /** Nights are [checkIn, checkOut): a guest checking out on the 15th doesn't occupy the night of the 15th. */
    synchronized boolean isAvailable(LocalDate checkIn, LocalDate checkOut, int rooms) {
        for (LocalDate d = checkIn; d.isBefore(checkOut); d = d.plusDays(1))
            if (booked.getOrDefault(d, 0) + rooms > sellable()) return false;
        return true;
    }

    synchronized boolean reserve(LocalDate checkIn, LocalDate checkOut, int rooms) {
        if (!isAvailable(checkIn, checkOut, rooms)) return false;              // check and write under ONE lock
        for (LocalDate d = checkIn; d.isBefore(checkOut); d = d.plusDays(1))
            booked.merge(d, rooms, Integer::sum);
        return true;
    }

    synchronized void cancel(LocalDate checkIn, LocalDate checkOut, int rooms) {
        for (LocalDate d = checkIn; d.isBefore(checkOut); d = d.plusDays(1))
            booked.merge(d, -rooms, Integer::sum);
    }
}

Details worth saying out loud:

  • Half-open date ranges [checkIn, checkOut): the checkout day is free for the next guest. Off-by-one errors here cause real double bookings.
  • Check and reserve under one lock, or in one database transaction. Checking availability and then reserving separately allows two guests to take the last room.
  • Cost: checking a stay is O(nights), regardless of how many rooms or reservations exist, which is much better than scanning every reservation for overlaps.
  • In a database, the same idea is a table of (room_type_id, date, total, booked) rows. A reservation increments booked on each night's row with a conditional update (WHERE booked + :n <= total * :factor), inside one transaction.

Assigning actual rooms at check-in

class RoomAssigner {
    Optional<Room> assign(Reservation r, List<Room> roomsOfType, Set<String> occupiedTonight) {
        return roomsOfType.stream()
                .filter(room -> !occupiedTonight.contains(room.number))
                .filter(room -> room.status == RoomStatus.CLEAN)
                .min(Comparator.comparing((Room room) -> !r.guest().prefersHighFloor() || room.floor < 5)
                               .thenComparing(room -> room.number));
    }
}

Assignment can consider preferences (floor, accessibility, connecting rooms) and housekeeping status. Separating selling nights from assigning rooms is what lets hotels keep flexibility, for example moving guests between rooms of the same type for maintenance, without touching reservations.

Reservation lifecycle

PENDING (held while paying) → CONFIRMED → CHECKED_IN → CHECKED_OUT, with CANCELLED and NO_SHOW as side exits. Each transition does something to the inventory:

  • An expired PENDING hold releases the nights.
  • A cancellation releases them, and applies the cancellation policy (free until 48 hours before arrival, then one night's charge). The policy is a Strategy chosen by rate plan.
  • A NO_SHOW keeps the charge, and releases the remaining nights for resale.

Pricing per night

The price of a stay is the sum of nightly rates, and each night may differ (weekends, seasons, events, occupancy). Model a RatePlan that returns a price for (room type, date), and compute the stay total by summing over the nights. A flat basePrice × nights breaks as soon as a stay spans a weekend.

Follow-up questions this topic invites — and their answers

Q: How would you extend isAvailable() to search across an entire RoomType rather than one specific room? A: Iterate the RoomType's rooms checking isAvailable() on each, returning the first (or all) available ones — the per-room interval check is the same, this just adds an outer loop; for a hotel with many rooms per type, this could be further optimized by only checking a subset if the caller just needs 'at least one available' rather than a full list.

Q: What's a concrete failure mode of the naive full-scan availability check at scale? A: A large hotel chain with years of reservation history and thousands of rooms would make every search request scan thousands of reservation records per room checked — the TreeMap approach keeps each individual room's lookup to O(log n) regardless of how much reservation history has accumulated.

Q: How would overbooking policy interact with the reservation confirmation flow from Movie Ticket Booking System's temporary-hold pattern? A: The same hold-with-expiry pattern applies directly — a room search result being 'available' doesn't guarantee it stays available through checkout, so a temporary hold during the booking flow prevents two guests from both confirming the same (already-overbooked-to-its-limit) room type simultaneously, exactly the same race the seat-booking hold pattern prevents.

Q: Should room pricing be a field on Room, or computed dynamically? A: Modeling it as dynamically computed (a PricingStrategy, matching the Strategy pattern used throughout this course) is generally the better design — real hotel pricing varies by date, demand, and length of stay, which a static price field on Room can't express, while a pluggable pricing strategy keeps that variability isolated from the room/reservation data model itself.

Q: Why track availability per room type and night rather than per room? A: Guests buy a room type for a set of nights. Counting sold nights against capacity makes availability checks O(nights), and keeps specific room assignment flexible until check-in, when housekeeping status and preferences are known.

Q: How do you prevent two guests from booking the last room at the same moment? A: Do the availability check and the increment atomically: under one lock in memory, or in a single transaction with conditional updates on each night's inventory row in a database. If any night fails the condition, roll back the whole reservation.

Q: Why are hotel stays usually modeled as [checkIn, checkOut)? A: The guest occupies the nights starting on each date from check-in up to, but not including, the check-out date. Treating the check-out date as occupied would block valid back-to-back bookings, and double-count the night.

Advertisement

Previous

Movie Ticket Booking System

Next

Airline Booking / Seat Selection System

AI Tutor

Lesson: Hotel Reservation System

Quick actions

AI responses can be inaccurate. Verify critical information.