The situation
The Operator manages short-term rental properties on behalf of the people who own them. That business only works if every property is visible on as many booking channels as possible — the big marketplaces plus the Operator's own direct booking site — because an empty week is revenue nobody gets back.
Listing everywhere is the easy part. The hard part is that each channel keeps its own calendar, and each one is perfectly willing to sell a week that another channel has already sold.
The problem
Availability lived in several places at once, and none of them was authoritative. A booking taken on one marketplace did not immediately close those dates everywhere else, so there was always a window — sometimes minutes, sometimes longer — in which the same week could be sold twice.
A double booking is not a small bug. Someone's holiday has to be cancelled, the Operator absorbs the cost of rehousing them, the owner of the property is unhappy, and the marketplace penalises the listing for the cancellation. The team had built a set of manual habits to catch these before guests did, which worked, but it meant a person was doing a computer's job every day.
Underneath that, property owners had no way to see how their own properties were performing. Every statement, payout question and occupancy query arrived as an email, and the operations team had quietly turned into a reporting desk.
What we built
The first decision was the one that mattered: availability became a single source of truth in PostgreSQL, and everything else was made to read from it rather than keep its own copy. Once that existed, the double-booking problem stopped being something to catch and started being something the system would not let you express.
Around that core, the team built the pieces the business actually ran on:
- A booking engine on the Operator's own site with real-time availability, so direct bookings — the highest-margin kind — no longer depended on a stale calendar
- A channel manager integration that synchronises availability and rates outward to the marketplaces and pulls reservations back in
- An owner portal where property owners see their own bookings, occupancy and statements without emailing anyone
- A guest portal covering the part of the trip after the booking — arrival details, check-in instructions, messaging
- Automated email and SMS workflows for confirmations, pre-arrival information and post-stay follow-up
The interesting decision
The existing system was written in CFML and running on Lucee, and there was a natural instinct to replace it. We argued against that, and it is worth explaining why.
Years of pricing rules, tax handling and payout logic were encoded in that CFML — the kind of logic that is tedious to write, extremely expensive to get wrong, and almost never fully documented anywhere else. Rewriting it would have meant re-deriving every one of those rules from scratch while the business kept trading on them.
So the CFML stayed where it was earning its keep, and ReactJS was introduced for the new interfaces. The new work went into the areas that were genuinely missing — the availability model, the portals, the channel integration — rather than into re-creating software that already worked.
Where it landed
Double bookings moved from an operational risk the team managed daily to a category of error the data model prevents. That is a different kind of fix: it does not need anyone to stay vigilant.
Owner reporting became self-serve, which took the recurring statement-and-occupancy traffic off the operations team and gave owners answers immediately instead of at the speed of an inbox. Guest communication that used to be sent by hand now runs on its own.
The engagement did not end at launch. The same team stayed on the platform, which is the arrangement most of this work ends up in — the value compounds once the people writing the code already know why every decision was made.
Client identity withheld by agreement. This account describes our own engineering work and deliberately omits any detail that could identify the client, including their name, brands, location and commercial figures.