Moving a tour operator off a rented ERP onto one they own
A tour and travel business running on a rented booking product wanted to stop paying per user for software they could not change. The catch: their team knew the old product well, and nobody wanted to lose a season to retraining.
Where they were
- Booking, hotel and flight operations ran inside a rented product the client could not modify. Every change request went into somebody else's roadmap.
- Costs scaled with headcount. Adding a person to the sales desk meant adding a licence, permanently.
- The data sat on the vendor's servers. There was no realistic path to taking it elsewhere intact.
- The team was fluent in the old product's screens. A conventional rebuild with a “better” interface would have cost them weeks of productivity in the middle of a season.
Where they are now
- The client owns the code, the database and the hosting accounts. There is no licence that expires and no vendor who can change the terms.
- Adding a staff member costs nothing in software. The per-user bill is gone.
- Sales, operations and accounts work in one system instead of a product plus side spreadsheets.
- Staff moved across without a training programme, because the flows were kept deliberately familiar.
- The customer-facing Android app and the internal ERP share one backend, so a package added once appears in both.
The decisions that shaped the system
Rather than redesigning the workflow, we mapped the existing product's screens and kept the booking flow recognisable. The interface is cleaner and faster, but a salesperson who knew the old system could work the new one the same afternoon. This was a design constraint, not an accident — the client's biggest risk was disruption, not features.
Sales, operations, accounts and admin each see a different system. Permissions are enforced at the data layer with row-level security rather than by hiding buttons in the interface, so an accounts login genuinely cannot read what it should not.
A managed Postgres database with row-level security underneath, a server-rendered Next.js application on top, deployed on Vercel. Small enough for one team to maintain, standard enough that another developer could pick it up — which matters more than novelty for a system a business depends on.
The ERP runs at a subdomain of the client's existing website, with DNS on Cloudflare. It looks and feels like their system because it is.
An Expo app for customers, reading tour packages from the same Supabase backend through PostgREST, with packages managed from the same admin panel. One source of truth for both surfaces.
The problem that did not look like a problem
After launch the client reported the system felt slow — roughly a second of lag on every click. Nothing was broken, nothing errored, and the code was not doing anything obviously expensive. That combination usually means the problem is not in the code.
It was geography. The Vercel functions were running in the US East region while the Supabase database sat in Sydney. Every page request was making several round trips between two continents, and each one cost a fraction of a second that added up to exactly the lag the client described.
Co-locating the functions with the database removed it. The longer-term plan is to move both to Mumbai, since every user is in India and the remaining latency is simply distance.
It is worth naming because it is the kind of issue that gets misdiagnosed as “the framework is slow” and triggers an expensive rewrite. It was a deployment setting.
Payments. The client's business line was declined by two payment gateways before CCAvenue approved an account in the client's own name. Rather than hold the app back waiting for a gateway, we shipped the Play Store release with online payment switched off and enquiry-based booking on, and added payments afterwards. Launching a useful app without one feature beat launching a complete app two months later.
About this project
Can you migrate us off a rented travel ERP too?
Do we have to change how our team works?
Have a project that looks like this one?
Tell us where you are now and what is breaking. We will tell you honestly whether a build is the right answer.