Designing a Hotel Booking System tests your ability to handle date-range availability, dynamic pricing, multiple room types, and cancellation policies — a great intermediate LLD problem frequently asked at OYO, MakeMyTrip, Cleartrip, and Expedia interviews.
Core Entities
- Hotel — name, location, amenities, rating
- Room — number, type, floor, base price
- RoomType — Single, Double, Suite, Deluxe
- Reservation — guest, room, checkIn, checkOut, status, price
- Guest — profile, reservation history
- PricingRule — defines price multipliers for dates/seasons
Availability Check
class RoomRepository {
findAvailable(hotelId: string, checkIn: Date, checkOut: Date, type: RoomType): Room[] {
const allRooms = this.getRoomsByType(hotelId, type);
const bookedRoomIds = this.reservationRepo.getBookedRoomIds(hotelId, checkIn, checkOut);
return allRooms.filter(r => !bookedRoomIds.has(r.id));
}
}Dynamic Pricing with Strategy
interface PricingStrategy { getPrice(room: Room, checkIn: Date, checkOut: Date): number; }
class DynamicPricing implements PricingStrategy {
getPrice(room: Room, checkIn: Date, checkOut: Date): number {
let total = 0;
for (let d = checkIn; d < checkOut; d.setDate(d.getDate() + 1)) {
let dayPrice = room.basePrice;
if (this.isWeekend(d)) dayPrice *= 1.25;
if (this.isPeakSeason(d)) dayPrice *= 1.5;
total += dayPrice;
}
return total;
}
}Cancellation Policy with Template Method
abstract class CancellationPolicy {
cancel(reservation: Reservation): CancellationResult {
const refund = this.calculateRefund(reservation);
reservation.status = ReservationStatus.CANCELLED;
this.paymentService.refund(reservation.paymentId, refund);
return { refunded: refund };
}
abstract calculateRefund(res: Reservation): number;
}
class FreeCancellationPolicy extends CancellationPolicy {
calculateRefund(res: Reservation) {
const hoursToCheckIn = (res.checkIn.getTime() - Date.now()) / 3600000;
return hoursToCheckIn > 24 ? res.totalPrice : res.totalPrice * 0.5;
}
}Common Questions
- "How do you prevent double booking?" → DB unique constraint on (roomId, date range overlap) + optimistic locking
- "How do you support early check-in?" → Add checkInTime field; pricing adjusts for partial day
- "How do you show room recommendations?" → Strategy for ranking (price, rating, availability)