Classic design · Senior
Hotel booking (Booking/Airbnb)
Classic interview design. Key points: reservations and concurrency.
Short answer
Classic interview design. Key points: reservations and concurrency. The classic exercise asks for the reservation system of a hotel chain: show the hotel page and the room detail page, book a room, cancel and manage hotel data. The customer pays the full amount at the time of booking, and hotel search is out of scope.
01 · CONTEXT
Little throughput, a lot of contention
The classic exercise asks for the reservation system of a hotel chain: show the hotel page and the room detail page, book a room, cancel and manage hotel data. The customer pays the full amount at the time of booking, and hotel search is out of scope. There is also a business requirement that complicates inventory: the chain accepts ten percent overbooking, that is, selling more rooms than exist, in the expectation that some customers will cancel.
The reference scale is a chain with five thousand hotels and one million rooms, with 70% occupancy and an average stay of three days. That gives about 240,000 reservations per day, or something like three reservations per second. Going down the funnel, the confirmation page gets about 30 queries per second and the detail page about 300.
The non-functional requirement that weighs most is high concurrency: in peak season or at big events, popular hotels get many customers trying to book the same room. Latency, on the other hand, is moderate: it is acceptable for the system to take a few seconds to process a reservation. That is why this case is, at heart, a concurrent write problem over a small inventory.
02 · MODEL
Book a room type, not a room
A modeling decision changes everything else: the reservation is made at the room-type level, not for a specific room. The customer books, for example, a double room at a hotel for certain dates, and the hotel assigns the physical room later. The inventory table stores, per hotel and room type, how many rooms exist and how many have already been reserved, with one row per date, which makes it simple to query and update a date range. Each reservation, in turn, moves through states: pending, paid, refunded, canceled or rejected. See the data modeling in action in the flow below.
The customer opens the chain's website or app; the request enters through the merchant API, which forwards it to the right service.
The hotel and room pages come from the hotel service, which reads the catalog. This data changes little and does not compete for inventory.
When the customer chooses a room type and dates, the reservation service generates a pending order with a unique identifier, which goes back to the customer for review.
On confirmation, the service writes the reservation and updates the inventory in the same relational database, in a single transaction.
If the customer cancels, the reservation changes state and the inventory's reserved quantity decreases, returning the room to stock.
03 · DOUBLE CLICK
The same user asking twice
Double selling has two different origins. The first is the same user submitting the reservation more than once, for example by double-clicking the button. The second is several users competing for the same room, covered in the next section. Disabling the button on the client helps, but is not reliable: the user can, for example, disable JavaScript and bypass the check.
The defense that counts is on the server: an API idempotente, which produces the same result no matter how many times it is called. In the book's design, the reservation service generates a unique identifier when creating the order, the client sends it on confirmation, and it is the primary key of the reservations table. If the user clicks again, the second write violates the uniqueness constraint and no duplicate reservation is created.
04 · LAST ROOM
Two users, one room
Suppose only one room is left and the database does not use the serializable isolation level. Two transactions read the inventory, both conclude there is still a vacancy, and each writes its reservation. Since one transaction's changes only become visible to others after the commit, the second still sees the old state. The result is that the system lets both users book, even though there is only one room. Fixing this generally requires some kind of lock or check at write time.
Two users request, almost at the same time, the last room of a type, for the same dates.
Each transaction reads the inventory and sees that one room is still free. Neither sees the other, because nothing has been committed yet.
With no protection, both write the reservation and commit. The stock says the room was sold, but two guests are entitled to it.
With one of the protections active, one transaction goes through and the other is rejected or waits. The rejected user is told that the room was just sold.
With pessimistic locking, the transaction locks the rows it read, and the others wait until it finishes. It is simple and serializes updates, but it can cause deadlock when several resources are locked and it hurts performance when transactions are long. Because of these limits, the book does not recommend it for this system.
With optimistic locking, a version column accompanies the row: on write, the application increments the version and the database checks that the new value is the expected one; if not, the transaction aborts. Without contention it is faster, because nothing is locked. Under heavy contention, only one of the clients manages to write and the others get a version failure and must retry. Since the reservation rate is usually low, the book considers it a good option here.
The third option is a constraint in the database itself, which rejects any state in which the total reserved exceeds the inventory. It is similar to the optimistic approach: easy to implement and suited to low contention, but under heavy contention it produces many failures. The book considers it another good option for the problem.
| Abordagem | How it prevents double selling | Main limit |
|---|---|---|
| Pessimistic locking | Locks the rows it read; other transactions wait | Deadlocks and performance loss with long transactions |
| Optimistic locking | Version column; writes only if the version has not changed | Many retries under heavy contention |
| Database constraint | The database rejects reserved stock above inventory | Many failures under heavy contention; rule lives outside the application's version control |
05 · SCALE
What if it were an entire travel site?
A common deep-dive question: what if the system served not one chain but a large travel site, with a load a thousand times greater? The services are stateless and scale by adding servers. The database, which concentrates all the state, is the bottleneck and does not scale with just more instances.
The way out is the particionamento of the database. Since almost every query filters by hotel, the natural key is the hotel identifier: a hotel's entire history lives in the same shard, and a reservation touches a single database. In the book's example, with thirty thousand queries per second spread across sixteen shards, each gets about 1,875 per second, within the capacity of a MySQL server.
The availability query, by far the most frequent operation, is answered by the inventory cache, without touching the database.
The reservation goes to the shard chosen by the hash of the hotel identifier and is validated by the database.
The database is updated first; a change-capture process reads what changed and sends it to the cache asynchronously.
The cache converges to the database state after a short interval.
In that interval the cache may show a room the database has already sold. The reservation reaches the database, which does the final validation and rejects it; the user sees that the room was just sold.
Inventory reads are an order of magnitude more frequent than writes, so a cache in front of the database greatly reduces the load. The book suggests Redis, because TTL and least-recently-used eviction help make good use of memory. Even when Redis shows a vacancy, the reservation is checked against the database, which is the source of truth for stock.
The cost is the consistency between database and cache. The database is updated first and the change flows to the cache asynchronously, through application code or change data capture (CDC), a mechanism that reads changes from the database and applies them in another system. The lag is acceptable, according to the book, as long as the database does the final stock validation.
06 · MICROSERVICES
Consistency across services
In a monolith, several operations fit in a single database transaction. In an architecture based on microservices, each service has its own database, and a logically atomic operation can span several services; so there is no single transaction to guarantee consistency.
The book cites two known ways out for distributed transactions. Two-phase commit (2PC) is blocking: the failure of one node halts progress until it comes back. A saga, on the other hand, is a sequence of local transactions; if a step fails, compensating transactions are run to undo the previous steps.
The book's choice for this problem was pragmatic: a hybrid approach, in which the reservation service handles the reservation and inventory APIs, keeping both tables in the same relational database and taking advantage of ACID properties. Deciding whether the extra complexity of distributing is worth it is, in the book's words, an architect's choice.
Frequently asked questions
What is Hotel booking (Booking/Airbnb)?
Classic interview design. Key points: reservations and concurrency.
What does the Hotel booking (Booking/Airbnb) design cover?
It is organized in these sections: Little throughput, a lot of contention, Book a room type, not a room, The same user asking twice, Two users, one room, What if it were an entire travel site?, and Consistency across services.
How long is Hotel booking (Booking/Airbnb) and what level is it?
It takes about 16 minutes to read and is rated Senior level.
Now design it yourself
Run this case as an interview in the System Design school: you make the decisions, the tutor challenges them and you see how your design scores.