Overbookings nobody could prevent.
Running multiple beach venues on a shared spreadsheet is not a workflow problem. It is a data-consistency problem wearing a workflow problem's clothes. Two managers opening the same sheet at the same time, tabbing down to the same slot, and hitting save — one of them always wins, and the other never knows they lost. The operator was comping unhappy guests two or three times a week because of exactly this.
The PMS vendors they'd evaluated all required an on-premise server, a per-seat licence, and a three-month onboarding. None of that fit a small operator with seasonal staff, no IT function, and a strong preference for not owning infrastructure. The brief was clear: we want something our managers can open in a browser, and we want it to not break.
A multi-property reservations console, with availability sync that doesn't poll.
The console gave every venue a live reservation grid — arrivals, departures, availability by slot, occupancy by date. A manager at one property could see concurrent changes from another property the moment they happened, without refreshing the page. Booking, modifying, and cancelling a reservation all updated the shared state immediately. Every open session saw every change as it landed.
Under the console: Firestore for reservation data, Realtime Database for the availability sync layer, Firebase Auth for session management, and Firebase Hosting for the static SPA. No Node server. No Express process to restart. No deployment pipeline beyond a single CLI command.
The analytics surface ran alongside the operational one: guest demographics, booking-trend charts via Highcharts, and a revenue-forecasting view pulled from the same Firestore collections the reservation grid was already reading. Built-in invoice generation (jsPDF) and CSV/XLSX export handled the owner's month-end workflow without a separate tool. Three and a half months from first commit to production.
- F · 01Live availability sync
- Firestore + Realtime Database push updates to every open session the moment a booking changes. No polling. No refresh.
- F · 02Multi-property dashboard
- One console spans all venues. Each property gets its own grid; the owner sees the full picture in a single tab.
- F · 03Firebase Auth session layer
- Firebase Auth manages sessions across owner, manager, and staff users. No custom auth server, no permissions table to maintain. Application-level role checks gate the surfaces.
- F · 04Invoice generation
- Booking confirmations and invoices produced client-side with jsPDF and emailed directly — no separate billing tool.
- F · 05Bulk import / export
- CSV and XLSX import for seasonal bulk-loading. Export for the owner's accountant at month-end. Both run in the browser.
- F · 06Analytics
- Guest demographics, booking trends, and a revenue-forecasting view built on Highcharts, reading the same Firestore collections as the reservation grid.
The Firebase-only choice, and why it survived production.
Concurrent reservation attempts on the same slot — two managers booking the last beach chair of the afternoon — was the exact failure the operator kept paying for. The fix wasn't write-side locking; it was read-side truth. Firestore's realtime listeners meant every open session on every device saw a booking the instant it was written. Once a slot was taken, every manager's screen showed it. The spreadsheet's coordination failure — two people working from stale views of the same row — couldn't happen, because nobody was working from a stale view.
The decision to skip a backend server entirely was not a cost-cutting shortcut. It was the right architecture for this operator's constraints. There was no DevOps team to babysit a Node process, no on-call rotation to hand to us, and no tolerance for a server going down on a Saturday in August. Firebase-managed services carry the availability guarantee; we carry the application logic. The boundary is clean.
Firebase Auth handled session management without a custom auth server. Multi-language support for an international guest base ran through ngx-translate. The static bundle deployed to Firebase Hosting in under two minutes. The total monthly infrastructure cost sat inside the Firebase free tier for the first six months of production.
Zero double-bookings. The infrastructure bill stayed inside free tier.
The overbooking problem stopped. In the first twelve months of operation, the operator recorded zero conflicting reservations on the same slot. The spreadsheet stayed open for a week after launch, as a fallback that nobody used.
The system went live across three properties simultaneously. The owner ran the staff training herself, over a single afternoon, because the console was simple enough to explain in one session. Seasonal staff turnover — the other reason the spreadsheet had been so fragile — stopped being a data-integrity risk once the state lived in the database, not in someone's local file. New seasonal hires got a Firebase Auth invitation and the same console everyone else used.
The product has run without a backend server since 2019. The operator has never filed an on-call page with us.
We stopped comping guests. That's the whole story.
