Insights

Why we rebuilt BATS CRM instead of patching it, and how nobody noticed

A code-generated CRM with paying customers had become hard to change. We assessed it, rebuilt it alongside the old system, migrated tenants in batches and retired the old infrastructure, with no downtime.

Davor Mićić, 8 October 2026

A product with paying customers is the hardest kind of software to change. BATS CRM had reached that point. It is a CRM platform for vehicle-transport brokers in the US, built on Code On Time, a code-generation platform that let the company build and ship its product fast and grow a real customer base on it. By 2024 the business wanted to take the product in a direction the generated application wasn't designed for, and every step in that direction was getting slower and riskier. The owner knew a rebuild was coming and knew the usual way that goes: a long gap with no releases, a second system that never quite catches up, customers who notice.

I came in as a consultant in 2024 to answer one question: what would it actually take?

Look before building

The first weeks were assessment, not code. Meetings with the owner about how the business and the product were supposed to work. Then the application itself: the data model, the generated code, the integrations, the parts customers depended on that nobody had written down. The output was a proposal with a scope, an estimate and a plan, and a recommendation that the rebuild was justified. Not because anything was wrong with the old platform; it had carried the company this far. The business simply wanted to go somewhere a generated application couldn't comfortably follow, and the cost of every future change was now higher than the cost of building the next version properly.

That proposal became the project. I recruited a second engineer, brought him into the codebase, and led delivery with the owner as product owner.

Plan from the existing system, not from a blank page

Most of the new platform was specified from what the old one already did. Where the behaviour was clear, we matched it. Where it wasn't, the owner explained it, and this time we wrote it down. Where it was wrong, we fixed it in the new version. This is slower to plan than starting fresh and much faster to ship, because the hard questions (what does this field mean, who uses this report, what happens when a broker cancels mid-load) had already been answered by years of real use.

The scope grew during the build, as it always does when a system is older than anyone's memory of it. We expanded the plan when we found things, told the owner what each one cost, and finished within the time that was appropriate for the scope we ended up with rather than the one we started with.

Two systems running at the same time

The new platform used a different database schema, so there was no way to flip a switch. Instead we deployed the new version alongside the old one and kept both running. The old system kept serving the customers who were still on it. The new one served the ones who had moved. Nothing in the business stopped.

Migrating customers in batches

We moved tenants in batches, not all at once. Each batch was migrated, verified against the old system, and used for real before the next batch moved. A problem found in batch two is a problem fixed before batch three. A problem found after a big-bang cutover is an incident for every customer at once.

The first release was not clean

It would be nice to say it went perfectly. The first release had issues, some of them the kind that detailed testing would have caught and ours didn't. We fixed them within the month. I plan more testing time now, and I say so when I scope projects; that is part of what the discovery sprint is for.

Retire the old system, then make the new one pay

Once every customer was on the new platform, we shut the old system down, including its infrastructure. Then we sized the new infrastructure to what the platform actually needed, which was less than the old one had been paying for. The migration didn't just remove risk; it cut the running cost.

What I'd tell an owner in the same position

Pay for an honest assessment first; it may tell you not to rebuild. If you do rebuild, specify from the system you have, not from scratch. Run both systems in parallel and move customers in batches, even though it is more work. Budget more testing than you think you need. And switch the old one off properly when you're done; a "just in case" system is a cost and a liability.

Today I lead technology for BATS CRM. The platform we built is the one we extend every week, which was the point.

Facing the same decision? A discovery sprint tells you whether to rebuild, what it would take, and what it would cost, before you commit. Book a 20-minute call.