← Back

Replacing a 200-person moving company's CRM — three years as their CTO, ending in a handover that proved it was finished

CTO of the build · 3 years · 10 developers

A Los Angeles–based moving and logistics company with around 200 employees had outgrown its industry CRM software. Three business units — long-distance moving, auto shipping, and local moving — were forced through one generic vendor workflow. Web leads leaked to competitors because nobody was assigned to them fast enough, supervisors approved pricing over email chains, and the system couldn't adapt to how each division actually worked.

Over three years I led a team of ten developers building a replacement platform. When the build phase ended, I transitioned the system to a four-person junior team at roughly 15% of the previous cost, trained them until it was safely in maintenance mode, and left. The system is still in production.

The decisions that mattered

One codebase, three businesses

The three divisions shared customers, pricing concepts, and operators — but almost nothing about their actual booking flow. Long-distance moves needed multi-phase scheduling, inventory management, and supervisor checkpoints. Auto shipping was carrier coordination with simple estimates. Local moving needed same-day speed above all.

The tempting options were a generic configurable workflow (which is exactly what the vendor software did, and why it failed) or three separate apps (three times the maintenance surface). I drew the line at shared domain models with three explicit, separately-built flows on top. It held up for three years of feature work, which is the only test that counts.

The rules that turned out to be defaults

During specification, the operations staff listed dozens of business rules — when a discount needs approval, what a quote must include, who can touch a booking at which stage. I encoded them as actual hard rules.

Reality disagreed. In practice, nearly every one of those rules had legitimate exceptions, and the people describing them as absolute were the same people who needed to override them a month later. Retrofitting override mechanisms — with permissions and traceability, not just an "ignore" button — into logic built as law was one of the harder technical stretches of the project.

Users describe their rules as absolute because that's how rules feel from inside a workflow. Since then I build them as enforced defaults with authorized escape hatches from day one.

Rebuilding pricing instead of porting it

The legacy system's pricing logic was full of accumulated quirks. We rebuilt the quoting engine from scratch — inventory complexity, add-ons, insurance, specialty handling — rather than replicating old behavior. It was the riskier call during migration, and the right one: it gave the business pricing flexibility the old software structurally couldn't offer.

A slow migration, chaos included

There was no big-bang cutover. A small group used the new system first while the rest stayed on the old one; when it was ready, everyone moved. The transition period meant real chaos: two systems running in parallel and a lot of double entry. That cost was accepted deliberately: with 200 people's daily work on the line, a gradual migration with a messy middle beat a clean-looking cutover that could stop the business.

What worked, what didn't — same lesson, both directions

The operator interface was keyboard-first and built by sitting with sales staff and watching how they actually handled calls. Adoption was immediate — it matched work that already existed.

We also built remote video survey capability for estimating moves. It was barely used. We had designed it for a workflow we imagined rather than one that existed. It changed how features were validated in years two and three: observed need first, build second.

The ending, which is the real result

When the platform was live, the economics changed: a ten-developer team made sense for building, not for running. The owner's first instinct was simply to lay everyone off.

I proposed something else: hire four junior developers at roughly 15% of the previous cost, and I would train them to own the system. Over the following period I moved the platform into maintenance mode, documented it, and coached the junior team until they were handling it independently. Then I left too.

I consider that handoff part of the deliverable. Software that only survives while its original team is on payroll isn't finished.

Handing off was the right call for this client's economics. It's not doctrine: my longest-running client made the opposite choice and keeps me on years later. Building handover-ready is what makes either option real.

What I'd do differently today

With current tools, I wouldn't need a team of ten — a build like this is now a two-or-three-person job with AI agents handling implementation under review. Having run the full-scale version is exactly what makes the compressed version safe: I know which parts of a system like this fail quietly, because I've watched them fail.

I'd also skip the SPA. The Vue 2 single-page frontend was the fashionable choice at the time; today I'd render server-side wherever possible and reserve rich client behavior for the few screens that earn it — less infrastructure, fewer failure modes, easier for a small maintenance team to own.

And the product itself would be AI-augmented in the places where it pays: lead enrichment and routing, drafting quotes and follow-ups for operator approval, call and email summaries flowing into customer history. Deliberately not in the places where it doesn't: binding price commitments, contract terms, and anything a customer signs stay deterministic. Knowing where that line sits is most of the job now.

What changed

I won't quote precise percentages — the client didn't run controlled measurements and neither did I. What I can stand behind:

  • The client funded the build for three full years, and when costs had to come down, chose to restructure around keeping the system rather than abandoning it.
  • Operators handled customers with visibly less effort; the keyboard-driven flow replaced slow form-hunting.
  • Payments went from scattered to centralized and automated through the integrated processor.
  • Reports and dashboards were used, not ignored — supervisors got real-time pricing approval instead of email chains.
  • Upselling additional services became easy enough that it actually happened, with revenue attached.
  • The system runs today, maintained by the team I trained.
Technical notes
  • Stack: Laravel + MySQL, with a Vue 2 SPA frontend.
  • Modular architecture (CRM, pricing engine, field app) with an API-first layer between modules.
  • Field surveys shipped as a PWA rather than native apps: instant updates and zero install/update cycle across a non-technical workforce outweighed native capabilities we didn't need.
  • Integrations: Gmail, SMS, Authorize.net payment processing, automated PDF estimates with digital signatures.
  • Process: Shape Up-style six-week cycles with cooldowns, sustained across ten developers for three years.
  • My role: de facto CTO — architecture, product direction, project leadership, and hiring. The ten-person team was highly autonomous under my supervision; I reported directly to the owner.