Markdown Editor

Hotel Reservation System Design Template

Hotel reservation system: room-type-per-night inventory, atomic multi-night holds, rate plans, LOS/CTA/CTD restrictions, overbooking model, channels, PMS

How to use: Use it when designing a hotel or lodging reservation system rather than seat-based ticketing. Fix the inventory unit (room type per property per night) and the portfolio numbers in section 3 first, then agree overbooking limits with revenue management. The main pitfall is booking nights one by one, which leaves stays with some nights reserved and others lost.

Preview

System Design: [Hotel reservation system name]

Reference design for a hotel group's central reservation system: inventory counted per room type and per night, multi-night stays booked atomically, rate plans with derived prices and stay restrictions (minimum length of stay, closed to arrival, closed to departure), an overbooking policy computed from show-up rates and walk costs, group blocks, and distribution of availability and rates to channels. It differs from seat booking in that nothing is sold by identity: a stay consumes one unit of a room type on each night, and the room number is assigned later. It follows the structure of the System Design Document template, adds a 45-minute interview path, access-pattern and failure-mode tables and a cited "How real systems do it" box, and is pre-filled with a worked design to adapt. Replace every [bracketed] value and every row marked Example; values marked Example are assumptions, not benchmarks.

Document control

FieldValue
Document ID[SDD-HR-001]
System / feature[Central reservation system]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Owner[@owner]
Author(s)[@author]
Reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
DifficultyIntermediate
Revenue management owner[@name]
Related[Payment ledger design], [Channel integration specs], [ADR: overbooking limits]

Approvals

RoleNameDecisionDate
Tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
Revenue management[@name][Decision]YYYY-MM-DD
Hotel operations[@name][Decision]YYYY-MM-DD
Security and payments[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Overbooking limit capped by walk probability, not only expected profit
0.3YYYY-MM-DD[@name]Example: Group blocks release to general inventory at cutoff
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: Our 1 200 hotels each run their own property management system, and the website, the call centre and two travel agencies each keep a copy of availability that is refreshed every 15 minutes. On busy weekends we sell rooms that no longer exist, front desks walk guests without a policy, and a three-night booking sometimes holds Friday and Saturday but loses Sunday. Rate changes take hours to reach all channels, so the same room shows three prices.]

1.2 Proposed solution

[Example: A central reservation system owns future inventory as counters per property, room type and night. A booking reserves one unit on each night of the stay in a single transaction on the property's shard, or fails as a whole. Rate plans are defined once (a base rate plus derived plans and restrictions) and priced per night. Availability and prices for search come from a precomputed calendar that is updated by events within seconds; the booking path always re-checks the counters. Overbooking limits per room type and night come from revenue management and are enforced as part of the counter check. Channels receive availability, rates and restrictions by push on every change, and reservations from channels enter through the same booking path. The PMS receives reservations and sends back in-house changes and out-of-order rooms.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: Unit of inventory?Counter per property, room type and night; no room numbers before check-in5, 7.1
Q-02Example: How to book several nights safely?One transaction with conditional decrements on all nights, rows locked in date order7.2
Q-03Example: Overbooking limit?Expected-profit optimum, capped so the chance of walking any guest stays at or below 10%7.5
Q-04Example: Channel inventory?One shared pool with last-room availability, not fixed allotments per channel7.6
Q-05Example: Search freshness?Precomputed calendar, lag p99 at or below 5 s; booking re-checks7.4
[Q-nn][Question][Option][Section]

1.4 45-minute interview path

Use this order when the document serves an interview or a short design review. The written sections below are the long form of each step.

MinutesCoverOutput on the whiteboard
0 to 5Scope: search, book, modify, cancel; one hotel group; room types, not rooms; below-the-line items (2.3)The inventory unit "room type x night"
5 to 10Estimates: rooms, bookings per day, searches per second, inventory rows (section 3)Four numbers, "reads dominate by 500 to 1, writes are tiny" consequence
10 to 15API: availability search, hold, confirm, modify, cancel with idempotency (section 4)Five calls
15 to 25High-level design: booking service on inventory store, calendar cache for search, channel and PMS sync (section 6)One diagram with a read path and a write path
25 to 40One deep dive: multi-night atomic booking (default, 7.2), or rate plans and restrictions (7.3), or overbooking (7.5)Options, choice, reason
40 to 45Failures (channel sync lag, PMS offline), the 10x row in section 10Two failure rows

Start the default deep dive with the naive answer: "for each night, read availability, then insert the booking". Show two guests booking the last Saturday room, one for Friday and Saturday and one for Saturday and Sunday, both reading 1 available. Then compare a lock per night, a conditional update per night in one transaction, and a single property lock, and explain why rows are locked in date order.

2. Requirements

2.1 Core functional requirements

IDRequirementPriority
FR-01Example: Search availability and prices by property or destination, dates, guestsMust
FR-02Example: Book a stay of 1 to 30 nights in one room type and rate plan, all nights or noneMust
FR-03Example: Rate plans with derived prices, inclusions, cancellation and deposit policiesMust
FR-04Example: Restrictions per night: minimum and maximum length of stay, closed to arrival, closed to departure, stop-sellMust
FR-05Example: Modify dates or room type; cancel within policyMust
FR-06Example: Overbooking within limits set per room type and nightMust
FR-07Example: Group blocks with a cutoff date after which unused rooms return to general inventoryShould
FR-08Example: Push availability, rates and restrictions to channels; accept their reservationsMust
FR-09Example: Send reservations to the PMS; receive out-of-order rooms and in-house changesMust
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements and invariants

IDQualityTargetMeasured as
NFR-01No oversell beyond policyExample: For every property, room type and night: sold plus held never exceeds rooms minus out of order plus the overbooking limitNightly audit
NFR-02Atomic staysExample: No booking with some nights reserved and others notAudit of booking nights against counters
NFR-03Search latencyExample: p95 at or below 300 ms for a property calendarSynthetic and real-user monitoring
NFR-04Booking latencyExample: p99 at or below 500 ms for hold and confirm, excluding paymentService timing
NFR-05FreshnessExample: Calendar and channels updated within 5 s p99 of a changeEvent age
NFR-06Availability (booking path)Example: 99.95% monthlySLO
[NFR-nn][Quality][Target][Measurement]

2.3 Below the line (out of scope)

Name these explicitly so reviewers and interviewers do not pull the design toward them.

  • [Example: revenue management forecasting and price optimisation (this system consumes their output)]
  • [Example: room assignment, housekeeping and check-in (PMS)]
  • [Example: loyalty points accrual (separate service fed by stay events)]
  • [Example: seat-based events and onsales (see Ticket and Hotel Booking System Design (system-design/design-ticket-booking))]
  • [Item deferred, with the release that will take it]

3. Capacity estimation

3.1 Assumptions

InputSymbolValueSource
PropertiesPPExample: 1 200Portfolio
Average rooms per propertyRRExample: 150Portfolio
Room types per propertyTTExample: 8Product catalogue
Rate plans per room typeQQExample: 12Revenue management
Booking horizonHHExample: 730 nightsProduct rule
Average occupancyooExample: 70%Last 12 months
Average length of stayℓ\ellExample: 2.2 nightsLast 12 months
Share of bookings later cancelledccExample: 25%Last 12 months
Availability queries per gross booking (look-to-book)kkExample: 500Channel and web logs

3.2 Bookings and searches

Rooms in the portfolio: P×R=1 200×150=180 000P \times R = 1\,200 \times 150 = 180\,000. Occupied room nights per day divided by length of stay gives arrivals, which equal net bookings in a steady state:

Bnet=180 000×0.702.2≈57 273 bookings/day,Bgross=Bnet1−c=57 2730.75≈76 364 bookings/dayB_{net} = \frac{180\,000 \times 0.70}{2.2} \approx 57\,273 \ \text{bookings/day}, \qquad B_{gross} = \frac{B_{net}}{1 - c} = \frac{57\,273}{0.75} \approx 76\,364 \ \text{bookings/day}
S=Bgross×k≈76 364×500≈3.8×107 queries/day≈442 queries/s average, 1 326 at a peak factor of 3S = B_{gross} \times k \approx 76\,364 \times 500 \approx 3.8 \times 10^{7} \ \text{queries/day} \approx 442 \ \text{queries/s average}, \ 1\,326 \ \text{at a peak factor of 3}

Booking writes are about 76 364/86 400≈0.976\,364 / 86\,400 \approx 0.9 per second on average and about 9 per second during a promotion at 10 times the average. Each booking touches ℓ\ell night rows, about 168 000 night-row updates a day.

3.3 Inventory and rate data

DataCalculationResult
Inventory rows1 200×8×7301\,200 \times 8 \times 7307 008 000 rows; at 200 bytes about 1.4 GB
Rate rows (price and restrictions per plan and night)1 200×8×12×7301\,200 \times 8 \times 12 \times 73084 096 000 rows; at 100 bytes about 8.4 GB
Search calendarOne entry per rate row, already pricedabout 8.4 GB, fits in a replicated in-memory cache

3.4 Summary

QuantityEstimateDesign consequence
Searchesabout 1 300 queries/s at peakSeparate read path from a precomputed calendar
Bookingsunder 10/s even in a promotionOne relational cluster sharded by property; contention, not volume, is the issue
Inventory7 million rows, 1.4 GBSmall; partition by property for single-shard stays
Rates84 million rows, 8.4 GBStore base and derivation rules; materialise for search only

4. API design

4.1 Endpoints

Method and pathPurposeNotes
GET /v1/properties/{id}/availability?checkin=&checkout=&adults=Room types and rate plans with total price for the stayFrom the calendar cache; may be seconds stale
POST /v1/holdsReserve inventory for a stay for 15 minutesRequires Idempotency-Key; re-checks counters
POST /v1/reservationsConfirm a hold with guest and guarantee detailsPayment by token only
PATCH /v1/reservations/{id}Change dates, room type or guestsNew nights held before old nights released, in one transaction
POST /v1/reservations/{id}/cancelCancel; returns the penalty under the rate plan policyIdempotent
PUT /v1/inventory/{property}/{room_type}/{date}Revenue management and operations: overbooking limit, stop-sell, out-of-order countAudited

The Idempotency-Key header follows the pattern of draft-ietf-httpapi-idempotency-key-header-08 (22 October 2026, an Internet-Draft, not an RFC). Errors use problem details (RFC 9457).

4.2 Request and response examples

Hold request:

{"property_id": "PRP-0417", "room_type": "KING-DLX", "rate_plan": "BAR", "checkin": "2027-03-11", "checkout": "2027-03-14", "adults": 2}

Hold response with the per-night breakdown:

{"hold_id": "HLD-88213", "expires_at": "2027-02-02T10:15:00Z", "currency": "USD", "nights": [{"date": "2027-03-11", "price": 180}, {"date": "2027-03-12", "price": 220}, {"date": "2027-03-13", "price": 240}], "total": 640, "cancellation_policy": "Free until 48 hours before arrival, property local time"}

A hold that fails on any night returns 409 with the failing night and the reason (sold_out, closed_to_arrival, min_los_not_met), so the client can suggest other dates.

5. Data model

5.1 Entities

Inventory and rates are keyed by property-local stay dates (a night is a date, not a timestamp). A reservation has one row per night it consumes.

5.2 Storage choices

DataStoreKeyWhy
Inventory nights, reservations, holdsExample: Relational database sharded by property_id(property_id, room_type, stay_date)Multi-row transactions on one shard
Rate plans and rate nightsSame shard as the property(property_id, room_type, rate_plan, stay_date)Pricing in the booking transaction reads local rows
Search calendarExample: Replicated in-memory cache(property_id, room_type, rate_plan) with a 730-night arrayOne key read per room type and plan
Change eventsPartitioned logproperty_idOrdered per property for calendar, channels and PMS
Payment tokensPayment provider vaultTokenCard data never stored in this system

5.3 Access patterns

Access patternFrequencyKey or index that serves itPartition key rationale
Show prices for a stay at one propertyabout 1 300/s at peakCalendar cache by (property_id, room_type, rate_plan)Search never touches the booking database
Hold a multi-night stayunder 10/sInventory rows (property_id, room_type, stay_date range)All nights of a stay are on the property's shard, so one local transaction
Price the stay inside the holdEvery holdRate night rows on the same shardNo cross-shard read in the transaction
Modify datesRareOld and new night rows of the same propertyStill one shard
Find a guest's reservationsSupport, guest appSecondary index on guest ID, or a separate lookup tableCross-property queries go to a read replica
Expire holdsEvery minuteIndex on hold.expires_at per shardSweeper per shard
Nightly auditDailyFull scan per shard of tomorrow's nightsBounded: 8 room types x 1 night per property

6. High-level design

ComponentResponsibilityScales by
Reservation APIAuthentication, routing of search to cache and writes to bookingStateless instances
Booking serviceHolds, confirms, modifications, cancellations; enforces counters and restrictionsStateless, routes by property shard
Inventory and reservation DBSource of truth for future inventory and reservationsShards by property
Calendar builderApplies change events to the search calendarPartitions of the change log
Channel pushSends availability, rate and restriction changes per channel formatPer channel worker pools
PMS connectorTwo-way sync with each hotel's PMSPer property queues

7. Detailed design

The deep dives in this section, each with options, choice and reason:

Deep diveOptions consideredChoiceReasonSection
Multi-night bookingRead then write per night; lock per night; conditional update per night in one transactionConditional updates in one transaction, rows in date orderAll or nothing, no deadlock, no long locks7.2
PricingStore every price; derive at read time; derive at write time and materialiseBase rates stored, derived plans materialised into the calendarOne source to change, fast search7.3
OverbookingNone; fixed percentage; computed per room type and nightComputed limit, capped by walk riskRevenue without uncontrolled walks7.5
Channel inventoryFixed allotments; shared poolShared pool with push on changeNo stranded rooms; one counter7.6

7.1 Inventory model

Sell room types, not rooms. A room number is chosen at or near check-in by the PMS, which lets the hotel absorb early departures, late check-outs and maintenance without touching reservations. For each property, room type and night:

available=physical−out_of_order+overbook_limit−sold−held\text{available} = \text{physical} - \text{out\_of\_order} + \text{overbook\_limit} - \text{sold} - \text{held}

A booking is allowed on a night only if available is at least 1 and the night is not stop-sold. NFR-01 is this inequality checked for every row.

7.2 Multi-night atomic hold

A stay from 11 to 14 March consumes the nights of 11, 12 and 13 March. The hold runs one transaction on the property's shard:

BEGIN;
-- lock the nights in date order first, so overlapping stays queue in the same order
SELECT stay_date FROM inventory_night
 WHERE property_id = 'PRP-0417' AND room_type = 'KING-DLX'
   AND stay_date >= DATE '2027-03-11' AND stay_date < DATE '2027-03-14'
 ORDER BY stay_date
 FOR UPDATE;
UPDATE inventory_night
   SET held = held + 1, version = version + 1
 WHERE property_id = 'PRP-0417' AND room_type = 'KING-DLX'
   AND stay_date >= DATE '2027-03-11' AND stay_date < DATE '2027-03-14'
   AND stop_sell = FALSE
   AND physical - out_of_order + overbook_limit - sold - held >= 1;
-- the service checks that the row count equals the number of nights (3);
-- if not, ROLLBACK and report the first failing night
INSERT INTO hold (hold_id, property_id, room_type, checkin, checkout, expires_at)
VALUES ('HLD-88213', 'PRP-0417', 'KING-DLX', DATE '2027-03-11', DATE '2027-03-14', now() + INTERVAL '15 minutes');
COMMIT;

The explicit SELECT with ORDER BY stay_date FOR UPDATE locks the nights in date order (an UPDATE over a range does not promise any lock order), so two overlapping stays always lock shared nights in the same order and cannot deadlock; the locks are held only for the few milliseconds of the transaction, never across payment. If the updated row count is less than the number of nights, at least one night is full or closed, and the transaction rolls back.

Confirming a hold moves the count from held to sold on each night and writes reservation nights with their prices. A sweeper releases expired holds by the reverse update. A modification holds the new nights and releases the old nights in the same transaction, so a guest who moves a stay never ends up with neither booking.

7.3 Rate plans and restrictions

Revenue management sets a base rate (best available rate, BAR) per room type and night. Other plans derive from it:

PlanDerivationPolicyExample for Thu 180, Fri 220, Sat 240
BARBaseFree cancellation until 48 h before arrival640 for 3 nights
NRFBAR minus 15%Non-refundable, charged at booking544
BB2BAR plus breakfast 18 per guest per nightAs BAR640 + 3 x 2 x 18 = 748
MEMBERBAR minus 10%, members onlyAs BAR576

The stay price is the sum of the nightly prices, each from that night's rate row, so a stay over a price change mixes prices correctly. Restrictions are evaluated against the arrival and departure dates:

RestrictionChecked onRule
Minimum length of stay (MinLOS)Arrival nightStay length at least the value set on the arrival night
Maximum length of stay (MaxLOS)Arrival nightStay length at most the value
Closed to arrival (CTA)Arrival nightNo stays may start on this night
Closed to departure (CTD)Departure dateNo stays may end on this date
Stop-sellEvery nightNo new holds for the plan or room type

Restrictions make availability depend on the stay, not only on the nights: a Saturday with MinLOS 2 is available for Friday to Sunday but not for Saturday alone. The calendar therefore stores restrictions next to prices, and the search evaluates them per requested stay.

7.4 Search calendar

The calendar builder consumes change events per property and keeps, for each (property, room type, rate plan), an array of 730 entries: available count, price, MinLOS, MaxLOS, CTA, CTD. A search for one property reads at most 8 x 12 = 96 keys and evaluates the stay in memory. Lag is the event pipeline lag (NFR-05). The cache can be wrong for a few seconds; the hold in 7.2 is always the final check, and a failed hold returns the failing night so the page can refresh.

7.5 Overbooking policy

Some guests do not arrive and some cancel too late to resell. Selling a few rooms above capacity raises expected revenue but risks walking a guest (relocating them to another hotel at the group's cost). With capacity CC, booking limit BB and independent show probability qq, arrivals follow X∼Binomial(B,q)X \sim \text{Binomial}(B, q). With cuc_u the margin of a room night lost when a room stays empty and coc_o the cost of walking one guest, the expected contribution is:

E[π(B)]=cu E[min⁡(X,C)]−co E[max⁡(X−C,0)]E[\pi(B)] = c_u \, E[\min(X, C)] - c_o \, E[\max(X - C, 0)]

Example: C=100C = 100, q=0.92q = 0.92, cuc_u = 150 (room rate 180 minus 30 variable cost), coc_o = 450 (relocation, transport, compensation and goodwill), all in USD:

Booking limit BBExpected contributionExpected walksProbability of at least one walkExpected empty rooms
10013 800.00.0000.0008.00
10414 328.20.0400.0294.36
10514 425.20.1080.0713.51
10614 482.40.2430.1402.72
10714 483.90.4700.2392.03
10814 418.00.8100.3591.45

The expected-contribution optimum is B=107B = 107 (an overbooking limit of 7), but it walks at least one guest on about 24% of such nights. With a policy cap of 10% on the probability of any walk, the limit is B=105B = 105 (limit 5), which gives up 58.7 of expected contribution per night (14 483.9 minus 14 425.2) to cut the walk probability from 0.239 to 0.071. Revenue management approves the cap; the system stores overbook_limit per room type and night and enforces it in 7.1. The binomial model assumes guests decide independently; groups and event nights break that assumption, so set lower limits there.

When arrivals exceed rooms, the walk workflow chooses which reservation to relocate (never loyalty top tiers or guests already walked on this trip, as Example rules), books a comparable nearby hotel, pays transport and compensation, and records the walk for the next forecast. Consumer rules on relocation and disclosure differ by country; check the local rules and a qualified professional. This is not legal advice.

7.6 Channels, group blocks and the PMS

  • Shared pool: channels sell from the same counters (last-room availability), so a room is never stranded in one channel's allotment. The channel push sends availability, rates and restrictions on every change, batched per property for 1 s. A channel that sells on a stale count sends a reservation that fails the hold; the gateway answers with a rejection the channel understands, and the lag is tracked per channel (9.3).
  • Group blocks: a block reserves rooms for a group as its own counter per night, taken out of general inventory. Guests book from the block until the cutoff date; at cutoff a job returns unused block rooms to general inventory in one transaction per property.
  • PMS: the central system owns future reservations; the PMS owns in-house stays and room assignment. Out-of-order rooms from the PMS raise out_of_order counts and can create a negative availability that triggers the walk workflow before arrival day rather than at the desk.

7.7 How real systems do it

How real systems do it (paraphrased, not copied). Rothstein's paper "Hotel overbooking as a Markovian sequential decision process" (Decision Sciences, 1974) describes a general hotel reservation system and models booking acceptance as a sequence of decisions; applied to sample data from a real hotel, cancellations were frequent enough that the model prescribed a substantial amount of overbooking. Talluri and van Ryzin's book "The Theory and Practice of Revenue Management" (Springer, 2004) treats overbooking and network revenue management, where a product such as a multi-night stay uses capacity on several resources at once, which is why 7.2 books every night of a stay together. Cross, Higbie and Cross, "Revenue Management's Renaissance" (Cornell Hospitality Quarterly, 2009), argue that hotel revenue management should move beyond room inventory control to total revenue, price elasticity and measures that compare performance with competitors. Read the originals in 12.3; this box keeps only the general ideas.

8. Scalability and performance

ConcernApproachLimit before redesign
SearchCalendar cache, replicated per regionExample: 20 000 queries/s with current nodes
HoldsSharded by property, short transactionsContention on one property's popular nights during a promotion
Channel pushBatched per property, per-channel workersChannel rate limits
Rate updatesDerived plans recomputed per changed base night onlyBulk yearly loads run off-peak
AuditPer shard, tomorrow's nights only, plus weekly full horizon[Limit]

Latency budget for a hold (target p99 500 ms):

StepBudget
API, authentication, idempotency lookup40 ms
Restriction check on rate nights30 ms
Inventory transaction (up to 30 rows)80 ms
Event publish20 ms
Headroom330 ms

9. Reliability, security and operations

9.1 Failure modes

ComponentFailureDetectionBlast radiusMitigationRTO
Property shard primaryFailoverError rate per shardProperties on that shard cannot book for secondsSynchronous replica; idempotent retries by clientsExample: 30 s
Calendar builderFalls behindEvent age above 5 sSearch shows stale availability; holds still correctScale consumers; banner on search if lag above 60 sExample: 5 min
Channel pushChannel endpoint downPush error rate per channelChannel sells on stale dataRetry with backoff; stop-sell that channel if lag passes 15 minExample: 15 min
PMS connectorHotel PMS offlineHeartbeat per propertyOne hotel's out-of-order and in-house updatesQueue changes; front desk works from PMS; reconcile on reconnectExample: hours, local
Hold sweeperStopsCount of expired holds not releasedInventory locked by abandoned holdsAlert; holds also checked for expiry at read timeExample: 5 min
Rate loadWrong prices loadedPrice change monitor (large jumps)Plans derived from the wrong baseVersioned rate loads; rollback to previous versionExample: 10 min
[Component][Failure][Signal][Scope][Mitigation][Time]

9.2 Security and abuse

ThreatControl
Card data exposureTokenisation at the payment provider; this system stores tokens only, keeping it out of cardholder data scope where possible
Inventory hoarding by bots (holds never confirmed)Holds per session and per IP limited; short TTL; holds by channels count against their quota
Rate scrapingRate limits per client; signed partner API keys
Guest data accessRole-based access; reservation lookup needs reservation ID plus surname or authenticated account
Tampering with overbooking limitsChanges audited and limited to revenue management roles

9.3 Observability

SignalMetric or logAlert threshold
Oversell beyond policyAudit violations (NFR-01)Any
Hold failure reasonsSold out, restriction, error, by propertyError share above 1%
Calendar lagEvent age at cache writep99 above 5 s
Channel lag and rejectionsPer channelLag above 60 s or rejection rate doubling
WalksWalked guests per property and nightAbove forecast from 7.5

9.4 Cost estimate

ItemUnit costQuantityMonthly cost
Database shards with replicas[$/node-month]Example: 8 shards x 3[$]
Calendar cache nodes[$/node-month]Example: 6[$]
Event log and consumers[$/month][Size][$]
Channel connectivity fees[/bookingor/booking or /month][Volume][$]
Total[$]

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
Unit of saleSpecific room; room type per nightRoom type per nightFlexibility for operations, simple countersGuests cannot pick a room number at booking
ConcurrencyPessimistic locks across payment; conditional updates plus hold TTLConditional updates and holdsShort transactions, no lock across network callsAbandoned holds block inventory for 15 min
PartitioningBy date; by propertyBy propertyStays and modifications stay on one shardCross-property guest queries need an index or replica
Channel inventoryAllotments; shared poolShared poolNo stranded roomsStale channels may sell into a full night and get rejected
PricesAll materialised; all derived at read; hybridBase stored, derived materialised for searchOne place to change rates, fast readsCalendar rebuild after base changes
What changes at 10x / 0.1x10x (12 000 properties, about 760 000 bookings/day): about 13 000 searches/s at peak, so the calendar cache becomes a regional tier and channels need dedicated push clusters; booking writes (about 90/s in promotions) still fit a sharded cluster. 0.1x (120 properties): one database with a replica and a read-through cache; overbooking limits may be set per property instead of per nightReview at each doubling of propertiesSearch and channel push grow first[Note]
[Decision][Options][Chosen][Why][Cost]

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Inventory model, holds and bookings for 10 pilot properties, web channelNightly audit clean for 30 daysYYYY-MM-DD
M2Rate plans, restrictions, calendar searchSearch p95 at or below 300 msYYYY-MM-DD
M3PMS connector and channel pushChannel lag p99 at or below 60 sYYYY-MM-DD
M4Overbooking limits and walk workflowWalk rate within forecast for one seasonYYYY-MM-DD

11.2 Migration and rollback

[Example: Migrate property by property. For each property, freeze availability changes for 10 minutes, load future reservations from the old system and the PMS, reconcile counts night by night, then switch channels to the new push. Rollback restores the old system as the source and replays reservations made in the new one.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: Migration counts differ from the PMSHighHighNight-by-night reconciliation before cutover[@name]
R-02Example: Overbooking model ignores groups and eventsMediumHighLower limits on flagged nights; review after each season[@name]
R-03Example: A channel cannot handle push frequencyMediumMediumPer-channel batching and rate limits[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Do we price by length of stay (different nightly price for 7-night stays)?[@name]YYYY-MM-DD
OQ-02Example: Should room upgrades at booking consume the higher room type's inventory?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.2 Glossary

TermMeaning
BARBest available rate; the base public rate from which others derive
ARIAvailability, rates and inventory sent to channels
MinLOS, MaxLOSMinimum and maximum length of stay, set on the arrival night
CTA, CTDClosed to arrival, closed to departure
WalkRelocating a guest with a reservation to another hotel because none is free
Out of orderRooms unavailable for sale because of maintenance
Group blockRooms reserved for a group until a cutoff date
Look-to-bookAvailability queries per booking
[Term][Meaning]

12.3 References

ReferenceUse
Rothstein, M. "Hotel overbooking as a Markovian sequential decision process", Decision Sciences 5(3), 389 to 404, 1974, doi:10.1111/j.1540-5915.1974.tb00624.x7.5, 7.7
Talluri, K. T. and van Ryzin, G. J. "The Theory and Practice of Revenue Management", Springer, 2004, doi:10.1007/b1390007.5, 7.7
Cross, R. G., Higbie, J. A. and Cross, Z. N. "Revenue Management's Renaissance", Cornell Hospitality Quarterly 50(1), 56 to 81, 2009, doi:10.1177/19389655083287167.7
draft-ietf-httpapi-idempotency-key-header-08 (Internet-Draft, October 2026) and RFC 9457 Problem Details4.1
Ticket and Hotel Booking System Design (system-design/design-ticket-booking)Seat-based inventory, waiting rooms and the simpler allotment model this design extends
E-commerce Checkout and Inventory System Design (system-design/design-ecommerce-checkout-inventory)Counted inventory reservations
Payment Ledger System Design (system-design/design-payment-ledger)Deposits, penalties and refunds
Back-of-Envelope Estimation and Capacity Model (system-design/back-of-envelope-estimation)Method for section 3

Standard and licence note

Based on common industry practice for hotel central reservation systems and on the revenue management literature cited in 12.3, paraphrased only. No standard governs this design. The overbooking table is computed from the stated example inputs with an exact binomial model; all prices, volumes and limits are illustrative examples, not benchmarks. Notes on relocation rules are not legal advice; check the current official text and a qualified professional. Original text written for this collection. Template licence: MIT.

Related templates