Portico Property Management System

Case study · Portico Property Management System

Guest lookup went from 3 to 5 seconds to 45 milliseconds at the front desk

Portico puts reservations, housekeeping and billing on one record, and matches the behaviour of the product front desk staff were trained on, so consolidation does not cost a retraining programme. It is in development, scheduled for five properties in 2027.

Snapshot

ClientHospitality software vendor, selling to hotels and resorts
StatusIn development. Not live yet.
Scheduled5 properties, 1,000+ rooms, 2027
BuiltProperty management: reservations, guest profiles, rates, housekeeping, cashiering, accounts receivable, reporting
StackLaravel, PHP 8, MySQL, Redis, Typesense, Next.js, Docker
TimelineJune 2025 to present, team of 14
My roleBackend lead

The Challenge

A property management system is the operational record of a hotel: front desk, housekeeping, cashier, night audit, accounts receivable, and the interfaces to door locks, telephony, the point of sale and in-room entertainment all read from it or write to it. It also never stops, because there is always a guest checking in.

Two things make replacing one hard.

  • Per-property behaviour is real. Tax treatment, folio routing, rate structures and transaction codes differ by property and by country. If those live in code, every new property is a development project rather than a setup task.
  • Staff are already trained on something else. The incumbent is Oracle Opera, and a system that is correct but behaves differently gets rejected at the front desk anyway. Hotel turnover is high enough that retraining is a recurring cost, not a one-time one.

The Approach

Behavioural parity with Opera, including the inconvenient parts. Availability calculation, nightly rate locking, folio routing and transaction code structure follow Opera semantics rather than a cleaner design of my own.

This is the decision the whole product rests on. For the buyer it means a receptionist who moves properties can work on day one. The cost is inherited complexity no greenfield design would choose: tax backed out of a gross figure, charges inheriting across group and subgroup levels, rates locking nightly rather than per stay. The team pays for that continuously, and the alternative is a better system nobody buys.

Property behaviour is configuration. Transaction codes, revenue buckets, routing rules, rate structures, room classifications and geography are administered records, not deployments. Bringing a new property online is a configuration exercise.

Search is built for someone standing at a counter. Guest lookup started as database text matching and took 3 to 5 seconds once the profile data reached realistic volume: a receptionist watching a spinner with a guest in front of them, on the most repeated action in the building. Indexing every profile in a dedicated search engine brought it to 45 milliseconds.

Ranking changed with it. Prefix matches now sort above mid-string ones, because a receptionist searches with whatever the guest offers, and a mid-string hit ranked first is the wrong answer for a human at a counter even when it is a correct match. The cost is a second datastore to keep consistent, which at roughly a hundredfold is worth paying.

Reports are templates the property controls. Layouts are dictated by the property and by local regulators and change without notice. Moving reporting onto a template engine cost a migration of every existing report and means a layout change is not a release.

The Build

Fourteen months, fourteen people. I led the backend from the first commit: the data model, the layered architecture the team extends, profiles, rooms, rates, reservations, transaction codes and cashiering, the billing posting engine, accounts receivable, Opera parity, search and reporting. The majority of the frontend is other people's work, as are the housekeeping interface, the queue infrastructure and the vendor interfaces.

The posting refactor was merged and reverted the same day. Billing posting is the path that touches guest money. The first attempt changed the orchestrator, the routing engine and batch posting together, which made the blast radius the entire billing domain and made the failure impossible to isolate. It went in, came out the next day, and was re-landed narrowed to one area.

The lesson is specific and I now apply it as a rule: a refactor of a financial path is scoped to what can be reverted without reverting everything around it.

A real-time stack was adopted and replaced within a week. Self-hosting the broadcasting layer looked reasonable until the cost of running it beside a system with no maintenance window was clear. Replaced with a hosted service.

Results

BeforeAfter
Source of truthSeparate systems that disagreeOne record
Bringing on a new propertyDevelopment workConfiguration
Report layout changeReleaseTemplate upload
Staff retrainingExpectedOpera parity, so largely avoided
Guest lookup3 to 5 seconds45 milliseconds, prefix-ranked

Nothing here is an operational result, because the system is not operating yet. No property is live. Five are scheduled for 2027, covering more than a thousand rooms. The search figures are measured against the system's own data, not against whatever those properties run today, and every other row is a design property rather than something someone has lived with. A property management system is judged on what happens during a busy check-in, and that has not happened yet.

Next

If your front desk, housekeeping and billing disagree with each other, the fix is one record rather than better reconciliation. Get in touch.

08 · Contact

Let's Build Something Useful

If you're looking for someone to develop business software, improve operational processes, or integrate existing systems, I'd be happy to discuss your project.