Hotel Management System β 75-Minute Interview Guide
Quick Start
What is it? A booking and management system for hotels with room inventory, reservations, check-in/out, payments, ratings, and customer management.
Key Classes:
- HotelManagementSystem (Singleton): Main coordinator
- Hotel: Multiple properties with rooms
- Room: Room status (available/booked/maintenance), room type (single/double/suite)
- Reservation: Guest booking with dates, status, pricing
- Guest: Customer profile, bookings, payment info
- Payment: Transaction handling
Core Flows: 1. Search: Guest enters dates β Find available rooms β Display options β Return 2. Book: Select room β Apply pricing β Create reservation β Confirm 3. Check-in: Guest arrives β Verify booking β Assign room key β Update status 4. Check-out: Guest leaves β Calculate charges β Process payment β Archive reservation 5. Cancel: Guest cancels β Apply penalty policy β Refund (if eligible)
5 Design Patterns:
- Singleton: One HotelManagementSystem manages all properties
- State Machine: Reservation states (pending, confirmed, checked-in, completed, cancelled)
- Strategy: Different pricing strategies (weekend, weekday, seasonal)
- Observer: Notify on room availability changes
- Factory: Create different room types
System Overview
Multi-property hotel management supporting room bookings, reservations, payments, guest management, dynamic pricing, and occupancy optimization for hotel chains.
Requirements
Functional: - Search available rooms by date range and type - Create and manage reservations - Check-in and check-out guests - Process payments and refunds - Manage room inventory and status - Handle cancellations with penalties - Generate bills/invoices - Rate rooms and hotels - Support multiple hotels
Non-Functional: - Booking response < 500ms - Support 1M+ daily searches, 100K+ concurrent bookings - 99.9% uptime - Accurate availability (no double-booking) - Transaction consistency
Constraints: - Prevent double-booking - Cancellation penalties: 0% (>7 days), 25% (3-7 days), 50% (<3 days) - Room capacity: 1-6 guests per room - Reservation hold: 1 hour without payment
Architecture Diagram (ASCII UML)
ββββββββββββββββββββββββββββββββ
β HotelManagementSystem β
β (Singleton) β
ββββββββββββββββββββββββββββββββ€
β - Search rooms β
β - Make reservation β
β - Process payment β
β - Manage occupancy β
βββββββββββββ¬βββββββββββββββββββ
β
βββββββββΌββββββββ¬βββββββββ
β β β β
βΌ βΌ βΌ βΌ
ββββββββ ββββββββ ββββββββ ββββββββββββ
βHotel β βRoom β βGuest β βReserv β
ββββββββ ββββββββ ββββββββ ββββββββββββ
Room Status Machine:
AVAILABLE βββ BOOKED βββ CHECKED_IN βββ CHECKED_OUT
β
(maintenance)
Reservation State Machine:
PENDING βββ CONFIRMED βββ CHECKED_IN βββ COMPLETED
β β
CANCELLED CANCELLED
Pricing Strategy:
PricingStrategy (ABC)
ββ WeekdayPricing: $100/night
ββ WeekendPricing: $150/night
ββ SeasonalPricing: $200-300/night
Room Inventory:
βββββββββββββββ
β Hotel ABC β
βββββββββββββββ€
β Room 101 β β Type: Single, Status: AVAILABLE
β Room 102 β β Type: Double, Status: BOOKED
β Room 103 β β Type: Suite, Status: CHECKED_IN
β Room 104 β β Type: Double, Status: AVAILABLE
βββββββββββββββ
Interview Q&A (12 Questions)
Basic Level
Q1: How do you prevent double-booking? A: Use atomic operations. On booking: (1) Lock room for date range, (2) Check if available, (3) Create reservation, (4) Unlock. If concurrent requests: first succeeds, others see unavailable. Use DB transactions or distributed locks (Redis).
Q2: What's a cancellation penalty policy? A: Depends on timing. >7 days before: 0% penalty (full refund). 3-7 days: 25% penalty. <3 days: 50% penalty. Day of arrival: 100% (non-refundable). Communicate clearly at booking time.
Q3: How do you generate a bill at checkout? A: Room charge = room_type_price Γ num_nights. Add extras (room service, parking, minibar). Apply discounts (loyalty, membership). Calculate taxes. Final bill = subtotal + taxes. Generate invoice for guest + accounting system.
Q4: What's the difference between room type and room status? A: Type: Single/Double/Suite (capacity, amenities). Permanent. Status: Available/Booked/Checked-in/Maintenance. Changes daily. Query by both: "Double rooms available on March 5?"
Intermediate Level
Q5: How to handle no-shows (guest books but doesn't arrive)? A: (1) Confirm 24 hours before (email/SMS). (2) At check-in time, if not arrived: mark as no-show. (3) Still charge (unless cancellation). (4) Release room after 2-hour grace period. (5) Track no-show rate per guest.
Q6: How to optimize pricing dynamically? A: Track occupancy rate. If >80%: increase price (less rooms, high demand). If <40%: decrease price (incentivize bookings). Update daily/hourly. Use algorithm: base_price Γ occupancy_multiplier. Prevents both overbooking and empty rooms.
Q7: What if guest overstays (stays past checkout)? A: (1) Notify guest at checkout time. (2) Allow grace period (30-60 min). (3) After grace: charge additional night. (4) Security can request departure if needed. (5) Log for repeat offenders.
Q8: How to handle group bookings (20+ rooms)? A: (1) Reserve block of rooms upfront, (2) Group discount (e.g., 10% off), (3) Single billing contact + master invoice, (4) Flexibility: guest can cancel specific rooms within group, (5) Special terms: guaranteed rate, flexible check-in.
Advanced Level
Q9: How to scale to 1000+ hotels? A: Geographic sharding: partition by region (North/South/East/West). Each region manages subset of hotels. Global search: fan-out to relevant regional databases. Aggregate results. Expected: <500ms latency with caching.
Q10: How to handle overbooking recovery? A: Intentionally overbook by 3-5% (some guests no-show). Monitor cancellation rate. If overbooked and guest arrives: upgrade to better room (no cost to guest) + compensation ($50 voucher). Document incidents.
Q11: How to prevent fraud (fake bookings, chargebacks)? A: (1) Verify payment method at booking, (2) Require ID at check-in, (3) Immediate charge (no pre-auth), (4) Flag suspicious patterns (multiple cancellations, multiple chargebacks), (5) Blacklist fraudsters.
Q12: How to optimize for revenue (maximize occupancy + rate)? A: Use ML: predict occupancy 30-60 days out β adjust pricing dynamically. Track competitor rates β match/undercut. Offer packages (room + breakfast) to fill rooms. Implement overbooking + service recovery.
Scaling Q&A (12 Questions)
Q1: Can you handle 100K simultaneous bookings? A: Message queue (Kafka): accept bookings β async processing. Process 1K bookings/sec = 100 seconds. For real-time feel: return confirmation immediately, notify if failed. Use optimistic locking to prevent conflicts.
Q2: How to prevent race conditions on room availability? A: Pessimistic lock: lock room during entire reservation process. Optimistic lock: version number, retry if mismatch. Distributed lock (Redis SETNX): lock room, release after booking. Trade-off: lock duration vs concurrency.
Q3: What if inventory data becomes inconsistent? A: Event sourcing: store all booking/cancellation events. Replay to reconstruct state. If inconsistency detected: replay from last known good state. Eventually consistent after 1-2 seconds. Acceptable for hotel booking.
Q4: How to handle peak season (80K bookings/day)? A: Scale horizontally: add servers. Pre-cache hot data (popular hotels, dates). Queue bookings if rate exceeds capacity. Implement circuit breaker: if system overloaded, return "try again later" (better than crash).
Q5: Can you support international bookings (multi-currency)? A: Store rates in base currency. On booking: convert to guest's currency using live exchange rate. Store both. At payment: charge in guest's currency. Convert for accounting in base currency. Update rates hourly.
Q6: How to generate analytics/reports? A: Data pipeline: booking events β Kafka β Spark β Data warehouse (BigQuery). Daily jobs: occupancy rate, revenue, cancellation rate, no-show rate. Reports available next day (acceptable lag).
Q7: What if payment processor is down? A: Retry logic: 3 attempts with exponential backoff. If failed: queue payment as pending. Retry daily for 7 days. If still failing: escalate to support team. Guest sees reservation pending until payment succeeds.
Q8: How to handle room modifications (guest wants different room)? A: Check availability of new room for same dates. If available: release old room, book new. If new room costs more: charge difference. Less: credit account. If not available: offer alternatives.
Q9: Can you support real-time room status updates (for staff)? A: WebSocket connection per staff member. On room status change: broadcast to all connected staff. Update frequency: 10-100ms. Ensures staff sees live status (e.g., "Room 101 checked out, ready for cleaning").
Q10: How to optimize database queries for million rooms? A: Index on (hotel_id, date_range, room_type_id). Partition DB by hotel. Query only relevant hotel's DB. Use Redis cache for popular queries (availability on peak dates). Expected query: <100ms.
Q11: How to handle auditing (compliance, taxes)? A: Log all transactions: booking, cancellation, payment, refund, adjustment. Store immutably (append-only). Generate monthly reports for accounting/tax compliance. Retain for 7 years.
Q12: Can you support third-party integrations (Booking.com, Expedia)? A: API gateway handles requests from OTAs (Online Travel Agencies). Inventory sync: OTA updates rooms sold through them, hotel updates availability. Dual-write: updates go to both hotel + OTA systems. Complexity: rate parity (ensure rates match).
Demo Scenarios (5 Examples)
Demo 1: Search & Book
- Guest searches: Check-in 2024-03-01, Check-out 2024-03-05
- Available rooms: Double ($150/night), Suite ($250/night)
- Select Double (4 nights Γ $150 = $600)
- Confirm booking
- Reservation created (status: PENDING)
Demo 2: Check-in & Check-out
- Guest John arrives for booking RES_001
- Front desk verifies ID
- Check-in: Room 201 assigned, key provided
- Status changes: CHECKED_IN
- After 4 nights: Guest requests check-out
- Final bill: $600 (room) + $50 (room service) + tax
- Payment processed
- Check-out: COMPLETED
Demo 3: Cancellation with Penalty
- Reservation RES_002: Check-in March 5 (booked March 1)
- Guest cancels March 2 (3 days before): 25% penalty
- Original: $300, Penalty: $75
- Refund: $225
- Room returned to available inventory
Demo 4: Dynamic Pricing
- Base price: $100/night
- Occupancy: 45% β Reduce to $80 (encourage bookings)
- Occupancy: 85% β Increase to $150 (maximize revenue)
- Weekend rates: +30% surcharge
- Seasonal (peak): +50% surcharge
Demo 5: Group Booking
- Corporate event: 20 Double rooms
- 5 nights: May 1-6
- Group rate: $120/night (vs $150 regular)
- Total: 20 rooms Γ 5 nights Γ $120 = $12,000
- Single master reservation
- Flexible cancellation (can cancel individual rooms with penalty)
Complete Implementation
"""
π¨ Hotel Management System - Interview Implementation
Demonstrates:
1. Room inventory management
2. Reservation booking with conflict prevention
3. Dynamic pricing
4. Check-in/out processes
5. Payment handling
"""
from enum import Enum
from typing import List, Optional, Dict
from dataclasses import dataclass, field
from datetime import datetime, timedelta
import threading
# ============================================================================
# ENUMERATIONS
# ============================================================================
class RoomStatus(Enum):
AVAILABLE = 1
BOOKED = 2
CHECKED_IN = 3
MAINTENANCE = 4
class RoomType(Enum):
SINGLE = 1
DOUBLE = 2
SUITE = 3
class ReservationStatus(Enum):
PENDING = 1
CONFIRMED = 2
CHECKED_IN = 3
COMPLETED = 4
CANCELLED = 5
# ============================================================================
# DATA CLASSES
# ============================================================================
@dataclass
class Room:
room_id: str
room_type: RoomType
hotel_id: str
status: RoomStatus = RoomStatus.AVAILABLE
floor: int = 1
def __hash__(self):
return hash(self.room_id)
@dataclass
class Guest:
guest_id: str
name: str
email: str
phone: str
payment_method: str = "Card"
@dataclass
class Reservation:
reservation_id: str
guest_id: str
room_id: str
hotel_id: str
check_in: datetime
check_out: datetime
status: ReservationStatus = ReservationStatus.PENDING
total_price: float = 0.0
created_at: datetime = field(default_factory=datetime.now)
def nights(self) -> int:
return (self.check_out - self.check_in).days
# ============================================================================
# HOTEL MANAGEMENT SYSTEM (SINGLETON)
# ============================================================================
class HotelManagementSystem:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if hasattr(self, '_initialized'):
return
self._initialized = True
self.hotels: Dict[str, List[Room]] = {}
self.reservations: Dict[str, Reservation] = {}
self.guests: Dict[str, Guest] = {}
self.room_counter = 0
self.reservation_counter = 0
self.lock = threading.Lock()
self.base_prices = {
RoomType.SINGLE: 100,
RoomType.DOUBLE: 150,
RoomType.SUITE: 250,
}
def add_hotel(self, hotel_id: str, num_rooms: int = 50):
with self.lock:
if hotel_id not in self.hotels:
rooms = []
for i in range(num_rooms):
self.room_counter += 1
room = Room(f"R{self.room_counter}", RoomType.DOUBLE, hotel_id)
rooms.append(room)
self.hotels[hotel_id] = rooms
print(f"β Added hotel {hotel_id} with {num_rooms} rooms")
def register_guest(self, guest_id: str, name: str, email: str, phone: str) -> Guest:
with self.lock:
guest = Guest(guest_id, name, email, phone)
self.guests[guest_id] = guest
print(f"β Registered guest: {name}")
return guest
def search_rooms(self, hotel_id: str, check_in: datetime, check_out: datetime, room_type: RoomType) -> List[Room]:
with self.lock:
if hotel_id not in self.hotels:
return []
available = []
for room in self.hotels[hotel_id]:
if room.room_type == room_type and room.status == RoomStatus.AVAILABLE:
# Check if room is booked for any date in range
is_booked = False
for res in self.reservations.values():
if (res.room_id == room.room_id and
res.status != ReservationStatus.CANCELLED and
not (res.check_out <= check_in or res.check_in >= check_out)):
is_booked = True
break
if not is_booked:
available.append(room)
return available[:10]
def make_reservation(self, guest_id: str, room_id: str, hotel_id: str,
check_in: datetime, check_out: datetime) -> Optional[Reservation]:
with self.lock:
if guest_id not in self.guests or hotel_id not in self.hotels:
return None
# Verify room exists and is available
room = next((r for r in self.hotels[hotel_id] if r.room_id == room_id), None)
if not room:
return None
# Check for conflicts
for res in self.reservations.values():
if (res.room_id == room_id and res.status != ReservationStatus.CANCELLED and
not (res.check_out <= check_in or res.check_in >= check_out)):
print(f"β Room {room_id} already booked for dates")
return None
# Calculate price
nights = (check_out - check_in).days
price = self.base_prices[room.room_type] * nights
self.reservation_counter += 1
reservation = Reservation(
f"RES_{self.reservation_counter}",
guest_id,
room_id,
hotel_id,
check_in,
check_out,
ReservationStatus.PENDING,
price
)
self.reservations[reservation.reservation_id] = reservation
guest = self.guests[guest_id]
print(f"β Reservation created: {reservation.reservation_id}")
print(f" Guest: {guest.name}, Room: {room_id}")
print(f" Dates: {check_in.date()} to {check_out.date()} ({nights} nights)")
print(f" Total: ${price}")
return reservation
def confirm_reservation(self, reservation_id: str) -> bool:
with self.lock:
if reservation_id not in self.reservations:
return False
res = self.reservations[reservation_id]
if res.status == ReservationStatus.PENDING:
res.status = ReservationStatus.CONFIRMED
print(f"β Reservation {reservation_id} confirmed")
return True
return False
def check_in(self, reservation_id: str) -> bool:
with self.lock:
if reservation_id not in self.reservations:
return False
res = self.reservations[reservation_id]
if res.status == ReservationStatus.CONFIRMED:
res.status = ReservationStatus.CHECKED_IN
# Update room status
for hotel_rooms in self.hotels.values():
for room in hotel_rooms:
if room.room_id == res.room_id:
room.status = RoomStatus.CHECKED_IN
print(f"β Check-in: Room {res.room_id}, Guest: {self.guests[res.guest_id].name}")
return True
return False
def check_out(self, reservation_id: str) -> float:
with self.lock:
if reservation_id not in self.reservations:
return 0.0
res = self.reservations[reservation_id]
if res.status == ReservationStatus.CHECKED_IN:
res.status = ReservationStatus.COMPLETED
# Release room
for hotel_rooms in self.hotels.values():
for room in hotel_rooms:
if room.room_id == res.room_id:
room.status = RoomStatus.AVAILABLE
guest = self.guests[res.guest_id]
print(f"β Check-out: Guest {guest.name}")
print(f" Total bill: ${res.total_price}")
return res.total_price
return 0.0
def cancel_reservation(self, reservation_id: str) -> float:
with self.lock:
if reservation_id not in self.reservations:
return 0.0
res = self.reservations[reservation_id]
if res.status in [ReservationStatus.PENDING, ReservationStatus.CONFIRMED]:
days_before = (res.check_in - datetime.now()).days
penalty = 0.0
if days_before > 7:
penalty = 0.0
elif days_before >= 3:
penalty = res.total_price * 0.25
else:
penalty = res.total_price * 0.50
refund = res.total_price - penalty
res.status = ReservationStatus.CANCELLED
print(f"β Reservation {reservation_id} cancelled")
print(f" Original: ${res.total_price}, Penalty: ${penalty}, Refund: ${refund}")
return refund
return 0.0
def display_status(self):
print("\n" + "="*70)
print("HOTEL MANAGEMENT SYSTEM STATUS")
print("="*70)
total_rooms = sum(len(rooms) for rooms in self.hotels.values())
booked = len([r for r in self.reservations.values() if r.status == ReservationStatus.CHECKED_IN])
print(f"Hotels: {len(self.hotels)}, Total rooms: {total_rooms}")
print(f"Total reservations: {len(self.reservations)}")
print(f"Currently occupied: {booked}")
# ============================================================================
# DEMO SCENARIOS
# ============================================================================
def demo_1_search_book():
print("\n" + "="*70)
print("DEMO 1: SEARCH & BOOK")
print("="*70)
system = HotelManagementSystem()
system.add_hotel("HOTEL_NYC", 20)
system.register_guest("G1", "John", "john@email.com", "555-1234")
check_in = datetime.now() + timedelta(days=5)
check_out = check_in + timedelta(days=3)
available = system.search_rooms("HOTEL_NYC", check_in, check_out, RoomType.DOUBLE)
print(f"β Found {len(available)} Double rooms available")
if available:
res = system.make_reservation("G1", available[0].room_id, "HOTEL_NYC", check_in, check_out)
if res:
system.confirm_reservation(res.reservation_id)
def demo_2_checkin_checkout():
print("\n" + "="*70)
print("DEMO 2: CHECK-IN & CHECK-OUT")
print("="*70)
system = HotelManagementSystem()
system.add_hotel("HOTEL_NYC", 10)
system.register_guest("G1", "Sarah", "sarah@email.com", "555-5678")
check_in = datetime.now()
check_out = check_in + timedelta(days=2)
available = system.search_rooms("HOTEL_NYC", check_in, check_out, RoomType.SINGLE)
if available:
res = system.make_reservation("G1", available[0].room_id, "HOTEL_NYC", check_in, check_out)
if res:
system.confirm_reservation(res.reservation_id)
system.check_in(res.reservation_id)
system.check_out(res.reservation_id)
def demo_3_cancellation():
print("\n" + "="*70)
print("DEMO 3: CANCELLATION WITH PENALTY")
print("="*70)
system = HotelManagementSystem()
system.add_hotel("HOTEL_NYC", 10)
system.register_guest("G1", "Mike", "mike@email.com", "555-9999")
check_in = datetime.now() + timedelta(days=2)
check_out = check_in + timedelta(days=3)
available = system.search_rooms("HOTEL_NYC", check_in, check_out, RoomType.DOUBLE)
if available:
res = system.make_reservation("G1", available[0].room_id, "HOTEL_NYC", check_in, check_out)
if res:
system.confirm_reservation(res.reservation_id)
system.cancel_reservation(res.reservation_id)
def demo_4_multiple_bookings():
print("\n" + "="*70)
print("DEMO 4: MULTIPLE CONCURRENT BOOKINGS")
print("="*70)
system = HotelManagementSystem()
system.add_hotel("HOTEL_NYC", 30)
for i in range(1, 4):
system.register_guest(f"G{i}", f"Guest {i}", f"guest{i}@email.com", f"555-{i}000")
check_in = datetime.now() + timedelta(days=7)
check_out = check_in + timedelta(days=4)
for i in range(1, 4):
available = system.search_rooms("HOTEL_NYC", check_in, check_out, RoomType.DOUBLE)
if available:
res = system.make_reservation(f"G{i}", available[i-1].room_id, "HOTEL_NYC", check_in, check_out)
if res:
system.confirm_reservation(res.reservation_id)
def demo_5_status():
print("\n" + "="*70)
print("DEMO 5: SYSTEM STATUS")
print("="*70)
system = HotelManagementSystem()
system.add_hotel("HOTEL_NYC", 20)
system.add_hotel("HOTEL_LA", 15)
for i in range(1, 6):
system.register_guest(f"G{i}", f"Guest {i}", f"g{i}@email.com", f"555-{i}111")
check_in = datetime.now()
check_out = check_in + timedelta(days=2)
for i in range(1, 4):
available = system.search_rooms("HOTEL_NYC", check_in, check_out, RoomType.SINGLE)
if available:
res = system.make_reservation(f"G{i}", available[0].room_id, "HOTEL_NYC", check_in, check_out)
if res:
system.confirm_reservation(res.reservation_id)
system.display_status()
# ============================================================================
# MAIN
# ============================================================================
if __name__ == "__main__":
print("\n" + "="*70)
print("π¨ HOTEL MANAGEMENT SYSTEM - 5 DEMO SCENARIOS")
print("="*70)
demo_1_search_book()
demo_2_checkin_checkout()
demo_3_cancellation()
demo_4_multiple_bookings()
demo_5_status()
print("\n" + "="*70)
print("β
ALL DEMOS COMPLETED")
print("="*70 + "\n")
Design Patterns Explained
| Pattern | Usage | Benefit |
|---|---|---|
| Singleton | HotelManagementSystem manages all properties |
Centralized booking coordination |
| State Machine | Reservation states (pending β confirmed β checked-in β completed) | Clear lifecycle |
| Strategy | Dynamic pricing (weekday, weekend, seasonal) | Flexible pricing algorithms |
| Observer | Notify on room status/price changes | Real-time updates |
| Factory | Create different room types | Type-specific behavior |
Summary
β Conflict prevention via pessimistic/optimistic locking β Dynamic pricing based on occupancy β Cancellation policies with penalties β Multi-property support with geographic scaling β State machine for reservations β Payment handling (charge at check-in or booking) β No-show management and overbooking recovery β Revenue optimization through pricing + occupancy β Scalable to 1000+ hotels with sharding β Thread-safe concurrent bookings
Key Takeaway: Hotel system demonstrates booking conflict prevention, dynamic pricing optimization, and multi-state reservation lifecycle. Core focus: preventing double-booking, revenue optimization, and scalability.