Requirements
- Search available rooms for a date range (check-in, check-out, guests, room type)
- Book a room: prevent double-booking the same room for overlapping dates
- Manage room inventory: hotel admins can add/remove rooms and configure pricing
- Handle cancellations with configurable cancellation policies
- 10K hotels, 1M rooms total, 100K bookings/day
Data Model
Hotel(hotel_id, name, address, city, country, lat, lng, rating, amenities[])
RoomType(room_type_id, hotel_id, name, capacity, bed_type, amenities[], base_price)
Room(room_id, hotel_id, room_type_id, room_number, floor, status ENUM(ACTIVE,MAINTENANCE))
Reservation(reservation_id, user_id, hotel_id, room_id, check_in, check_out,
status ENUM(PENDING,CONFIRMED,CANCELLED), total_amount, created_at)
RoomPrice(room_type_id, date, price) -- per-night pricing, overrides base_price
Availability Search
Query: find available rooms at Hotel H for check-in C1 and check-out C2.
SELECT r.room_id, rt.name, rp.price
FROM Room r
JOIN RoomType rt ON r.room_type_id = rt.room_type_id
LEFT JOIN RoomPrice rp ON rp.room_type_id = rt.room_type_id AND rp.date = :check_in
WHERE r.hotel_id = :hotel_id
AND r.status = 'ACTIVE'
AND r.room_id NOT IN (
SELECT room_id FROM Reservation
WHERE status IN ('PENDING', 'CONFIRMED')
AND check_in :check_in -- overlapping date ranges
)
Date overlap condition: two ranges [A,B) and [C,D) overlap iff A < D AND B > C.
Booking Flow (Preventing Double-Booking)
- User selects room and dates
- POST /reservations/hold: create Reservation with status=PENDING, expires_at=NOW()+15min
- User confirms and pays
- POST /reservations/{id}/confirm: BEGIN TRANSACTION; check no other CONFIRMED reservation overlaps (SELECT COUNT(*) … FOR UPDATE); if clean, charge payment; UPDATE status=CONFIRMED; COMMIT
The SELECT FOR UPDATE at step 4 acquires a row-level lock on the room’s reservations, preventing concurrent bookings. The hold (PENDING) at step 2 uses an INSERT with a UNIQUE constraint check to prevent creating two PENDINGs for the same room+dates simultaneously.
Availability Cache
Availability queries are read-heavy (users search many times before booking). Cache available room counts per hotel per date range in Redis: key=avail:{hotel_id}:{date}, value=hash of room_type_id → available_count. TTL=60s. Invalidate on booking and cancellation. Slight staleness (60s) is acceptable — the actual booking still validates in the DB. This reduces load on the reservation query by 90%+.
Dynamic Pricing
Hotel admins set per-night prices via the RoomPrice table. Price depends on: day of week, season, local events, current occupancy (yield management). Occupancy-based pricing: if occupancy > 80% for a date, apply a 1.2x multiplier. Computed nightly by a batch job. The active price for a room type on a date is: COALESCE(RoomPrice.price, RoomType.base_price). Cache the price in Redis with the availability data.
Cancellation Policy
Policy types: FREE_CANCELLATION (cancel anytime for full refund), PARTIAL_REFUND (50% refund if cancelled >48h before check-in), NON_REFUNDABLE. On cancellation: check policy and calculate refund amount; initiate refund via payment processor; UPDATE Reservation SET status=CANCELLED; add room back to available inventory (cache invalidation + DB update). Cancellation within 24h of check-in: apply the strictest policy.
Overbooking Handling
Airlines overbook intentionally; hotels may do so unintentionally. When a hotel is overbooked (more confirmed reservations than rooms): walk the guest (book them at an equivalent or better hotel, pay the difference). Track walked_reservations for SLA monitoring. Prevention: use SELECT FOR UPDATE strictly and cap pending reservations to available_rooms + 5% buffer.
Key Design Decisions
- Overlap condition: A < D AND B > C — memorize this for availability queries
- Two-phase booking (PENDING → CONFIRMED) with expiry gives users time to complete payment
- SELECT FOR UPDATE at confirm time prevents the race condition between two users booking the same room
- Per-night RoomPrice table enables dynamic pricing without schema changes
Airbnb system design is the canonical hotel reservation interview topic. See common questions for Airbnb interview: hotel reservation and availability system design.
Amazon system design covers booking and reservation systems. Review design patterns for Amazon interview: reservation and booking system design.
Stripe system design covers payment flows for reservation systems. See design patterns for Stripe interview: payment and reservation system design.