Design Airbnb (Hotel Reservation System)
[!NOTE] This module explores the core principles of Design Airbnb (Hotel Reservation System), deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.
1. Problem Statement
Designing a reservation system like Airbnb or Expedia involves more than just a search engine. The core complexity lies in Inventory Management: ensuring that a room is never booked by two people at the same time (Double Booking), especially during high-demand events (like the Eras Tour or World Cup).
The Hard Part: Maintaining strict accuracy across distributed servers when thousands of users click “Book Now” simultaneously.
2. Requirements & Goals
Functional Requirements
- Search Properties: Find available listings based on location, dates, and guests.
- Book Property: Reserve a property for specific dates.
- Payment Integration: Securely process payments to confirm the booking.
- Manage Listings: Owners can update availability, photos, and prices.
Non-Functional Requirements
- Strong Consistency: We cannot allow double-bookings (crucial).
- Availability: Users must be able to search even if the booking service is slow.
- Low Latency: Search results must be fast.
- Idempotency: Clicking “Pay” twice shouldn’t charge the user twice.
3. High-Level Architecture
The system distinguishes between the Search Path (read-heavy, eventual consistency OK) and the Booking Path (write-heavy, strong consistency REQUIRED).
4. Deep Dive: Zero-Double-Booking Strategy
How do we prevent two users from booking the same room? We use Database Locking.
Option A: Pessimistic Locking
The database locks the row the moment a user starts the checkout.
BEGIN TRANSACTION;
SELECT room_count FROM rooms WHERE id = 123 FOR UPDATE; -- LOCKS THE ROW
UPDATE rooms SET room_count = room_count - 1 WHERE id = 123;
COMMIT;
- Pros: Guaranteed accuracy.
- Cons: If a user sits on the payment page for 5 minutes, others are blocked. Low throughput.
Option B: Optimistic Locking (Recommended)
Add a version column. We only update if the version hasn’t changed.
UPDATE rooms SET
room_count = room_count - 1,
version = version + 1
WHERE id = 123 AND version = current_version;
- Pros: High throughput; no row-level locking until the actual commit.
- Cons: If 100 people try at once, 99 will get a “Conflict” error and have to retry.
[!TIP] Analogy: The Last Slice of Pizza Pessimistic: You put your hand on the pizza slice while deciding if you want it (no one else can take it). Optimistic: Everyone tries to grab the slice at once. The first hand that touches it wins; everyone else misses.
5. Handling Payments and Inventory
A common bug: The payment succeeds, but the inventory update fails. Now you have money but no room.
Solution: The Reservation Pattern.
- Reserve: Mark the room as “Pending” in the DB.
- Payment: Call the Payment Service (Stripe).
- Confirm: Only if payment is successful, update the status to “Booked.”
- Timeout: If payment isn’t received in 10 minutes, a background worker releases the “Pending” lock.
6. Scaling Search
Search requires complex filtering (Price < $200, Has WiFi, Near Beach).
- Read-Replicas: Use multiple read-only copies of the main DB for basic lookups.
- Elasticsearch: Sync property metadata to Elasticsearch for rich, high-performance search queries.
- Geospatial Indexing: Use Google S2 or H3 to quickly find properties within a specific map coordinate.
7. Interview Gauntlet
- How do you handle high-traffic dates (New Year’s Eve)?
- Ans: Use a Distributed Lock (Redis) or a Virtual Queue to limit the number of users entering the checkout flow simultaneously.
- What if the property owner updates the price during a user’s checkout?
- Ans: Capture the price at the moment the “Reserve” call is made. The user pays that price. This is a common business rule (Price Guarantee).
- How do you ensure Idempotency for payments?
- Ans: Every booking has a unique
booking_id. Pass this ID as anIdempotency-Keyto Stripe. If the request is retried, Stripe returns the original success instead of charging again.
- Ans: Every booking has a unique
8. Summary
- Consistency: Use the RDBMS (Postgres) and Optimistic Locking for inventory safety.
- Payments: Use the “Reserve → Pay → Confirm” state machine.
- Search: Use Elasticsearch for flexible, low-latency filtering.
- Recovery: Use background workers to clean up expired or failed reservations.