Database and API Optimization for a Hotel Booking Platform
Let's Connect
Overview
What we built
A hotel booking platform's search was so slow at busy times that travellers waited up to 14 seconds for a page of rooms. We reworked the database behind it, and searches now come back in under a second.
In plain terms: when a traveller searched for a hotel, the platform had to ask its database a long series of inefficient questions to build the results. At quiet times that was merely slow; at peak times, with 4,000+ searches arriving every hour, it brought the whole platform to its knees. Results took 8 to 14 seconds to appear, the database server ran at 95% CPU, and the system teetered whenever demand, and therefore revenue, was at its highest.
We fixed the problem at its source instead of adding bigger servers. Queries were restructured, targeted indexes were added so the database can find rooms without scanning everything, Redis caching now remembers recent answers with smart invalidation to keep them accurate, and connection pooling removed the overhead of opening a fresh database connection for every request. Search results now load in 0.9 seconds instead of 11, peak CPU sits at 34%, there have been zero timeout incidents in 6 months, and infrastructure costs are down 40%.
The Problem
Search grinding at peak load
Search is the front door of a booking platform: every reservation starts with a traveller asking which rooms are available. This platform handled 4,000+ search queries per hour, and each one triggered far more database work than it needed, with query patterns fetching related records one at a time instead of together. That waste was invisible at low traffic and unmissable at peak.
During busy periods the symptoms stacked up. Search results took 8 to 14 seconds to appear, long enough for a traveller to give up or start the search again, which only added more load. The database server climbed to 95% CPU, leaving no headroom, so every additional search made every other search slower, and slowdowns spilled into timeouts precisely when booking demand peaked.
The team's options inside the existing setup were poor. Throwing hardware at a database running inefficient queries buys temporary relief at permanent cost, and none of it addresses the underlying patterns: missing indexes forcing full scans, no caching layer, so identical searches were recomputed every single time, and a fresh connection opened for each incoming request.
One-at-a-time queries
Search code fetched related records individually instead of together, multiplying round trips to the database for every single results page it built.
Missing indexes
Without targeted indexes, availability lookups forced the database to scan far more data than each search actually needed, burning CPU on every request.
No caching layer
Identical popular searches were recomputed from scratch every time they were asked, so the database kept repeating the same expensive work at peak.
Connection churn
Each request opened its own database connection rather than reusing one from a pool, adding overhead and contention exactly when traffic was heaviest.
What it was costing them
Peak periods are when a booking platform earns, and peak periods were exactly when this one struggled. Travellers waiting 8 to 14 seconds for results abandon their searches, retries piled extra load onto a server already at 95% CPU, and the business paid for infrastructure sized around inefficiency while timeouts threatened bookings at the busiest, most valuable hours.
The Solution
Database and caching overhaul
We treated the database as the product and worked through it methodically. The first step was restructuring the query patterns behind search, replacing the one-at-a-time record fetching that ran throughout the codebase with consolidated queries that gather everything a results page needs in far fewer round trips to the database.
Targeted indexes were then added around the availability lookups that dominate search, so the database finds matching rooms directly instead of scanning its way to them. On top of that we implemented Redis caching with smart invalidation: frequently requested results are served from memory, and cached entries are cleared the moment the underlying data changes, so speed never comes at the price of showing a traveller a stale room.
Finally, database connection pooling replaced the connection-per-request pattern, so peak traffic reuses a managed set of connections instead of overwhelming the server with setup work. Each change reduced load on its own; together they changed the shape of the platform's peak hours, turning the database from the component everyone watched nervously into one with headroom to spare.
Key decisions
Fix queries before hardware
Restructuring inefficient query patterns attacked the actual cause of the slowdowns, where bigger servers would only have rented time against the same problem.
Index what search touches
Indexes were added deliberately around the lookups that dominate search traffic, rather than indexing broadly and paying the write-time cost everywhere.
Cache with smart invalidation
Redis serves repeated searches from memory, and invalidation clears entries as soon as data changes, so cached speed never shows travellers stale availability.
Pool database connections
Connection pooling reuses a managed set of database connections across requests, removing per-request setup overhead exactly where peak traffic made it most expensive.
Resolve the pattern everywhere
The one-record-at-a-time query pattern was resolved throughout the codebase, not just on the search path, so the fix does not erode as features change.
Measurable Impact
What changed after launch
Search result load time fell from 11 seconds to 0.9 seconds, taking the platform's core interaction from painful to effectively instant. At peak load the database server now runs at 34% CPU instead of 95%, which means busy periods come with headroom rather than a countdown, and in the 6 months following the optimisation there have been zero timeout incidents.
The efficiency gains showed up on the bill as well as the stopwatch. With the database doing a fraction of its former work per search, infrastructure costs fell by 40%, and the platform absorbs its 4,000+ searches per hour without drama. Peak demand is now an opportunity for the business again rather than an operational threat.
Search speed
Results taking 8 to 14 seconds at peak
Search results loading in 0.9 seconds
Database load
Server pinned at 95% CPU during peaks
Peak CPU usage down to 34%
Platform reliability
Timeouts and slowdowns through every busy period
Zero timeout incidents in 6 months
Infrastructure spend
Capacity sized around inefficient queries
Infrastructure costs reduced by 40%
Headline results
Search result load time reduced from 11 seconds to 0.9 seconds
Database CPU usage dropped from 95% to 34% at peak load
Zero timeout incidents in the 6 months following optimisation
Infrastructure costs reduced by 40%
Ready to Build your Travel & Hospitality Business with Performance & Optimization
Ask Byte
Ask Byte
Typically replies instantly
just Now
Hi! I'm OrganByte's assistant. How can I help you today?
AI-generated content may be incorrect

