How We Built Active Away’s Booking System: From Complex Sports Holidays to a Production-Ready Platform
Active Away does not sell simple products.
A tennis holiday is not one item dropped into a basket. It is an event place, a room, a guest profile, a rooming list, possible room sharing, extra nights, transfers, upsells, promo codes, deposits, balances, currencies, supplier confirmations, payment records and plenty of real-world exceptions.
That is why we needed more than a standard booking form.
We needed a booking system that could support the way Active Away actually works, from the moment a customer chooses a holiday to the point a hotel receives a confirmed rooming list. It had to be clear for customers, practical for the team, reliable for finance and strong enough to handle thousands of bookings.
This is the story of why we built it, how it works, and why it matters.
The problem: sports holidays are complicated
Most booking systems are built around simple assumptions.
One product. One date. One price. One payment.
Active Away is different.
A single booking can include:
- Event places
- Different room types
- Room sharing
- Extra nights
- Airport transfers
- Optional extras
- Upsells
- Promo codes
- Deposits and balances
- Multi-currency payments
- Hotel confirmations
- Agent commission
- Legacy customer history
Each of those moving parts affects the customer experience, the admin workload, and the financial record.
The old admin experience was becoming too heavy for that reality. In one early booking-wizard note, the old flow could expose around 300 events at once. That is a lot for any team member to sort through when they just want to create or manage a booking quickly and accurately.
For a business handling thousands of bookings and millions in annual revenue, small mistakes can become expensive. A room selected incorrectly, a transfer missed, an exchange rate changed at the wrong time, or an admin override without a clear record can create extra work for the team and confusion for the customer.
So the brief became clear: build a system that understands complex sports holidays from the ground up.
Why we built a custom platform
We could have tried to force Active Away’s operation into an off-the-shelf tool.
But that would have meant more workarounds, more spreadsheets, more manual checking, and more risk.
The business needed one central place for bookings, pricing, rooms, payments, transfers, agents, customer records and operational reporting. It also needed to bring previous booking history into a more modern customer portal, without losing the detail that matters.
The main goals were simple:
- Reduce manual admin work
- Keep pricing and availability controlled by the server
- Support legacy booking imports
- Give customers one clear portal
- Track financial decisions properly
- Give admins the tools to handle real-world exceptions
- Make refunds, overrides and booking changes auditable
The most important decision was this: the front end should collect what the customer wants, but the server should decide what is valid.
That matters because pricing and availability are too important to leave to fragile front-end calculations. If a customer changes a room, adds a guest, applies a promo code, chooses a transfer or pays in another currency, the system needs to verify the outcome properly before the booking is accepted.
What the booking system does
The platform now supports several connected workflows.
For customers, it provides a guided booking flow. They can search events, select rooms, add guest details, choose extras and transfers, review pricing, and pay either a deposit or a balance where available.
For admins, it gives the team tools to create and manage bookings, review payments, confirm rooms, handle refunds, export data, manage events and manage products.
For agents, it allows bookings to be created with commission tracked.
For hotels and suppliers, it supports rooming lists, secure hotel confirmation links and password-protected rooming-list views.
For finance, it records pricing, payment history, tax breakdowns, currency decisions, refunds and admin changes in a way that can be audited.
This is the key difference between a booking form and a booking platform.
A form takes information.
A platform helps the business run.
The technology behind it
The booking system was built with:
- Next.js 16
- React 19
- TypeScript
- Prisma
- PostgreSQL
- Tailwind
- NextAuth
The scale of the system reflects the complexity behind the scenes.
The repository currently contains roughly 8,440 TypeScript and TSX files, around 1,403 API route files and 534 app pages. The Prisma schema includes 407 models and 147 enums. There are around 2,378 test and spec-related files.
Those numbers are not there for show. They are a sign of how many different situations the platform needs to handle.
A booking system for this kind of business cannot only work when everything is perfect. It has to cope with the edge cases too: failed webhooks, duplicate submissions, payment delays, admin changes, capacity conflicts, room availability issues, booking imports, refunds and reconciliation.
Starting with the real business model
The build started with a detailed domain brief.
That meant mapping the core pieces of the Active Away operation:
- Products
- Locations
- Events
- Rooms
- Seasonal room rates
- Rooming lists
- Transfers
- Payments
- Users
- Notifications
- Reporting
- Customer history
This mattered because the system had to match the business, not the other way round.
For example, rooms are not just labels on a checkout page. They connect to locations, availability, seasonal rates, guest rules and hotel operations. Transfers are not just optional extras. They are location-specific, priced per person and tax-aware. Upsells may be attached to events and need to be tracked for fulfilment.
Once those relationships were understood, the system could be designed around server-side business rules and a layered architecture. That gives the platform a stronger foundation, because the logic lives where it can be validated, tested and audited.
The booking wizard: simple on screen, strict behind the scenes
One of the biggest customer-facing changes is the booking wizard.
The aim was not to show everything at once. It was to help customers and admins reach the right option quickly.
The wizard is broken into clear stages:
- Event filtering
- Room selection
- Guest details
- Extra nights
- Transfers
- Upsells
- Review
- Payment
The event search uses cascading filters: product, location, then month.
That sounds simple, but it solves an important operational problem. Instead of loading a huge list of events, the system narrows the results step by step. This makes the experience faster, easier to understand and less likely to overwhelm the person using it.
Room selection then checks more than whether a room appears to exist. It checks event person-type rules and seasonal room-rate availability. Later steps handle guest details, extra nights, transfers, upsells and payment review.
The important principle is this: the interface collects intent, but the server confirms the truth.
So if a customer chooses a room, adds a transfer, applies a promo code or reaches the payment step, the system verifies price, availability and submission validity before anything is final.
That protects the customer and the business.
Pricing that can be trusted
Pricing is one of the hardest parts of any complex booking system.
Active Away pricing can include room costs, early booking discounts, margins, profit per person, taxes, transfers, upsells, promo codes and customer currency.
The platform was built to treat pricing as a financial record, not a temporary calculation.
Booking schema v2 added roughly 140 booking columns, including 38 locked pricing fields and 123 edge-case fields. That may sound like a lot, but it allows the system to store the details needed to explain how a price was reached.
It also keeps the storage impact low. The estimated extra pricing storage is only around 1 to 2 KB per booking, or roughly 10 to 20 MB for 10,000 bookings.
That is a small technical cost for a major operational benefit.
Locked pricing fields mean the system can preserve the financial facts attached to a booking. Exchange rates can be locked when the booking is created or first paid, which prevents later currency changes from altering the customer’s agreed price.
That is essential. Once a customer has agreed to a price, the business needs a reliable record of that price, the tax breakdown, the deposit, the balance, the currency and any relevant adjustments.
Deposits, balances and payment flows
The payment system supports Opayo payments, 3D Secure, deposits, balances, payment deadlines and manual bank-transfer support.
That flexibility matters because not every customer journey is identical.
Some customers may pay a deposit first. Others may need to settle a balance. Admins may need to record a bank transfer. Finance may need to review overdue balances or reconcile payments against bookings.
The system also needs to account for the less tidy parts of online payments:
- Failed payments
- Failed webhooks
- Duplicate submissions
- Race conditions
- Capacity conflicts
- Reconciliation jobs
A good booking platform does not assume every payment completes perfectly first time. It plans for what happens when it does not.
That is why payment and booking flows use server validation, request IDs, hardened API responses and reconciliation processes. The goal is straightforward: keep booking records accurate, even when the real world gets messy.
Admin tools built for real operations
A common mistake in platform builds is focusing only on the customer-facing journey.
That was not enough here.
The admin tools had to be built alongside the booking flow because Active Away’s team needs to manage the exceptions that happen every day.
Admins can create and manage bookings, review payments, confirm rooms, handle refunds, export data, manage events and manage products. They also need visibility over customer history and previous bookings, especially where legacy records have been imported.
Admin overrides are supported, but they need to be tracked. Pricing snapshots and audit trails help show what changed, when it changed and why that matters financially.
That gives the team more confidence.
It also reduces reliance on memory, side notes and spreadsheet-style processes.
Rooms, rooming lists and hotel confirmations
Behind every confirmed holiday is a practical question: where is everyone staying?
The system connects rooms to locations and seasonal rates. When bookings are confirmed, rooming lists can automatically allocate rooms. Hotels can then confirm rooms through secure token links, and rooming-list views can be password protected.
That creates a cleaner process for the team and for suppliers.
Instead of chasing scattered information, the system can produce structured rooming data and confirmation flows. That helps reduce manual work and lowers the risk of information being missed or copied incorrectly.
For a customer, this work is mostly invisible.
That is the point.
The customer gets a smoother experience because the operational detail behind the booking is better organised.
Agents, CRM and rebooking insight
The system also supports agent bookings and commission tracking.
That means agent activity can sit within the same operational framework as direct customer bookings, rather than being managed separately.
Customer history and legacy booking imports also play an important role. Active Away has long-standing customers, and previous booking information can help support better service, clearer records and stronger rebooking insight.
A modern portal is not only about what happens next. It should also understand what has happened before.
Security and production readiness
Because the platform handles bookings, payments and customer data, security and reliability had to be designed in from the start.
Authentication supports admin, super admin, contractor, agent and customer roles. Sensitive workflows use server validation, rate limits, CSRF and origin checks, request IDs and hardened API responses.
The system also includes background cron routes for cleanup, reconciliation, reminders and operational automation.
These details are not always visible in the customer journey, but they matter. They help protect the platform from common failures, reduce operational risk and make the system more dependable in production.
Production readiness is not just about launching a feature.
It is about knowing what happens when a customer clicks twice, when a payment response is delayed, when capacity changes, when a webhook fails, or when an admin needs to correct something without losing the financial history.
The human outcome
The point of the booking system is not the technology itself.
The point is what it makes possible.
Customers get a cleaner booking experience. They can move through the booking flow with less confusion and more confidence.
Admins get fewer manual calculations, clearer workflows and better tools for managing exceptions.
Finance gets locked pricing, payment history, tax breakdowns and auditability.
Hotels and suppliers get more structured confirmation and export flows.
Agents can create bookings with commission tracked properly.
The business gets a scalable platform instead of a pile of disconnected processes.
That is the real value.
Built for the way Active Away works
The Active Away booking system was built because the business had outgrown generic booking tools.
Its value is not just that it takes bookings. Its value is that it understands the operational reality behind every booking: rooms, guests, payments, margins, suppliers, agents, legacy history and the exceptions that happen in real life.
A simple booking form might be enough for a simple product.
But Active Away sells detailed sports holidays with real people, real rooms, real payments and real operational responsibility.
So we built a platform to match.
Cleaner for customers.
Clearer for the team.
More reliable for the business.
And ready for the next stage of Active Away’s growth.