Skip to content
32.1 System Design: Distributed Hotel Reservation & Booking System (Inventory Locking, Overbooking Prevention, Two-Phase Holds)

32.1 System Design: Distributed Hotel Reservation & Booking System (Inventory Locking, Overbooking Prevention, Two-Phase Holds)

What it is

A distributed hotel reservation system coordinates room inventory, temporary holds, payment, and final confirmation across properties and channels. Inventory locking reserves sellable capacity without pretending that a booking is final, while a two-phase hold prevents a payment success from silently outranking confirmed inventory.

How it works

A search request reads an availability projection, but the booking command writes to an inventory authority. The authority stores room type, stay dates, total sellable units, committed units, active holds, and a version. A hold is a short-lived reservation with a unique hold ID, guest, price, expiry, and idempotency key.

The first phase creates the hold atomically. The service checks calendar overlap, decrements available capacity for the hold, records the payment intent, and returns a client secret. A timer publishes an expiry event. A late payment callback can confirm only an active hold whose version and external reference still match. After payment succeeds, the second phase converts the hold into a confirmed booking; if confirmation fails, the hold is released and the payment state follows an explicit compensation or manual-review path.

    sequenceDiagram
    participant Guest as Guest
    participant Booking as Booking service
    participant Inventory as Inventory authority
    participant Payment as Payment processor
    participant Timer as Hold expiry worker
    Guest->>Booking: Create booking with idempotency key
    Booking->>Inventory: Atomically create hold
    Inventory-->>Booking: Hold ID and expiry
    Booking->>Payment: Authorize payment for hold
    Payment-->>Booking: Authorized or declined
    alt Hold remains valid
        Booking->>Inventory: Convert hold to confirmed booking
        Inventory-->>Booking: Confirmed inventory and booking version
        Booking-->>Guest: Confirmation
    else Hold expires or payment fails
        Timer->>Inventory: Release expired hold
        Booking->>Payment: Cancel or reverse authorization
        Booking-->>Guest: Failure with stable status
    end
  

A hold record should never be inferred from a client timer. The authoritative expiry is a database or event-scheduled transition, and a reconciler compares holds with property calendars, payment intents, and booking records. Overbooking prevention depends on serializing changes for the same property, room type, and date range, rather than relying on an eventually consistent read.

A practical hold contract is:

CREATE TABLE room_holds (
  hold_id UUID PRIMARY KEY,
  booking_key VARCHAR(128) NOT NULL UNIQUE,
  property_id BIGINT NOT NULL,
  room_type_id BIGINT NOT NULL,
  stay_start DATE NOT NULL,
  stay_end DATE NOT NULL,
  units INTEGER NOT NULL,
  state VARCHAR(24) NOT NULL,
  expires_at TIMESTAMP NOT NULL,
  payment_id VARCHAR(128),
  version BIGINT NOT NULL
);

The booking transaction locks or conditionally updates the relevant inventory rows, verifies all requested nights, inserts the hold, and records an outbox event in one durable transaction. A service retry uses the same booking key and returns the existing hold or conflict if the request fingerprint differs.

Tradeoffs

  • Database row or calendar locks — make capacity decisions clear, but serialize contention for popular properties and date ranges.
  • Optimistic versioning — improves concurrent throughput, but retries conflicts and requires deterministic error handling.
  • Short holds — reduce blocked inventory, but increase the risk of payment completion after expiry.
  • Long holds — improve conversion, but strand inventory when a guest abandons checkout.
  • Synchronous inventory confirmation — gives immediate certainty, but couples booking latency to the inventory service.
  • Asynchronous confirmation — improves availability during outages, but needs pending states and careful client messaging.

When to use

  • Multiple channels compete for the same room inventory.
  • A guest must hold inventory while payment is authorized.
  • Payment callbacks can arrive after a client timeout or hold expiry.
  • Overbooking has financial, operational, or regulatory consequences.
  • The system must explain every hold, release, and confirmed booking.

Alternatives

  • Centralized booking database — provides straightforward consistency, but concentrates traffic and availability.
  • Optimistic inventory counters — reduce lock contention, but require safe retry and drift detection.
  • Queue-based hold workers — absorb bursts, but make the booking result asynchronous and operationally visible.
  • Provider or channel-managed inventory — reduces integration work, but limits control over cross-channel holds and policy.

Related