# System Design Interview: Design a Hotel Reservation System

Source: https://www.techinterview.org/post/3233462959/system-design-hotel-reservation-system/
Updated: 2026-04-17 · techinterview.org

## What Is a Hotel Reservation System?

A hotel reservation system manages room inventory, bookings, availability search, and payments for hotels. Examples: Booking.com, Expedia, hotel property management systems. Core challenges: preventing double-booking (two guests booking the same room on the same dates), real-time availability across thousands of hotels, and handling the booking flow atomically (reserve inventory → charge payment → confirm).

- [DoorDash Interview Guide](https://techinterview.org/doordash-software-engineer-interview/)

- [Lyft Interview Guide](https://techinterview.org/lyft-software-engineer-interview/)

- [Uber Interview Guide](https://techinterview.org/uber-software-engineer-interview/)

- [Shopify Interview Guide](https://techinterview.org/shopify-software-engineer-interview/)

- [Stripe Interview Guide](https://techinterview.org/stripe-software-engineer-interview/)

- [Airbnb Interview Guide](https://techinterview.org/airbnb-software-engineer-interview/)

## System Requirements

### Functional

  - Search available rooms by location, dates, room type, guests

  - Book a room: reserve, charge, confirm

  - Cancel a booking with refund based on cancellation policy

  - Hotel management: add rooms, set pricing, view bookings

### Non-Functional

  - 500K hotels, 10M rooms

  - Search: <200ms, 10K searches/second

  - No double-bookings under concurrent load

  - 99.99% uptime during peak season

## Core Data Model


```
hotels: id, name, location_id, star_rating, amenities
room_types: id, hotel_id, name, max_guests, base_price, total_count
room_inventory: id, room_type_id, date, available_count, price_override
bookings: id, user_id, room_type_id, check_in, check_out,
          total_price, status, payment_id, created_at
```


## Availability Search

For a search (hotel_id, check_in, check_out, guests): query room_inventory for all dates in the range. A room type is available only if available_count > 0 for EVERY date in the range.


```
SELECT room_type_id, MIN(available_count) as min_available
FROM room_inventory
WHERE hotel_id = ?
  AND date >= check_in
  AND date  0
```

Index on (hotel_id, date) makes this efficient. Pre-generate room_inventory rows for all room types for the next 365 days when a hotel is created.

## Preventing Double-Booking

Two users search at the same time, both see 1 room available, both click book. Without coordination: both succeed and the same physical room has two reservations. Solution: pessimistic locking with SELECT FOR UPDATE across all relevant inventory rows inside a transaction.


```
BEGIN TRANSACTION;
-- Lock all inventory rows for this booking
SELECT available_count FROM room_inventory
WHERE room_type_id = ? AND date >= ? AND date < ?
FOR UPDATE;
-- Check all dates still have availability
IF MIN(available_count) = ? AND date < ?;
-- Create booking
INSERT INTO bookings (...) VALUES (...);
COMMIT;
```

The FOR UPDATE acquires row-level locks on all inventory rows. The second concurrent transaction must wait until the first commits or rolls back. No double-booking possible.

## Booking Flow


```
User clicks "Book"
  → Reserve inventory (DB transaction, FOR UPDATE)
  → Hold reservation for 10 minutes (status = pending)
  → Redirect to payment page
  → Process payment (Stripe)
  → On payment success: confirm booking (status = confirmed)
  → On payment failure: release inventory (rollback reservation)
  → After 10-minute timeout: auto-release if payment not completed
```

The 10-minute hold prevents holding inventory indefinitely if the user abandons checkout. A background job cancels expired pending bookings and increments available_count back.

## Pricing: Dynamic Rates

Hotels set base prices; pricing engine adjusts based on demand. price_override column in room_inventory stores the adjusted price for a specific date. Computed by a nightly pricing job using occupancy forecasts. At search time, return the price for the specific dates requested (not just base_price).

## Caching Availability

Availability search results cached in Redis with 30-second TTL. Key: "avail:{hotel_id}:{check_in}:{check_out}:{guests}". Cache is invalidated on any booking for the same hotel. Trade-off: a user may see "1 room available" but lose the race at booking time — this is acceptable. The error message "this room was just booked" is a standard user experience on booking platforms.

## Interview Tips

  - room_inventory table with one row per (room_type, date) is the key data model — enables per-night pricing and availability.

  - SELECT FOR UPDATE across all date rows is the correct double-booking prevention.

  - 10-minute reservation hold + background cleanup is the checkout flow standard.

  - Availability caching is approximate — the DB transaction is the source of truth.
