Our host’s warning boiled down to this: the dedicated servers are old enough that if a part breaks, they can’t promise to fix them. It didn’t say “upgrade recommended.” It said they can’t promise parts.

That moved “migration” from our wish list to our risk register. Production runs on hardware with an unknown timer, and the timer starts when something snaps.

So we’re moving, and the legacy application is coming with us as-is.

What the last big rewrite cost

A forced migration looks like the natural moment to modernize. New box, new stack, clean slate. We distrust that instinct because we’ve paid the rewrite tax once already.

The one time we bet years on building something big and new, our team’s throughput dropped to roughly a third of its peak and stayed there for three years. The core product limped along while the future got built. The business shrank while we did it. Whatever a modern stack would eventually have saved, building it cost more than the debt it was supposed to clear. A third of peak across twelve straight quarters is the number I’d want a skeptic to hold us to, and it’s why “just modernize” stopped sounding free.

The legacy stack is unfashionable, but it isn’t the problem. It serves paying customers every day, we know every inch of it, and with AI agents in the loop we ship faster in this codebase than we ever have. New tech is development overhead until proven otherwise, and overhead doesn’t generate profit by default. Results do.

Pulling the two problems apart

The hardware problem and the technology problem are different problems, and only one of them has a deadline. The hardware problem is urgent, physical and non-negotiable. The technology question is discretionary, and it should be judged on economics with the adrenaline of a crisis kept out of the math.

The sequence we settled on:

  1. Cloudflare in front of the server. Every domain, every pointer, every customer DNS setting now resolves to the edge instead of straight to the old box. This was months of work, mostly a long tail of customer-managed domains. It’s the enabling move, because it makes what comes next invisible to customers.
  2. The hardware move, now an infrastructure swap behind a stable layer. Database over, app over, flip Cloudflare to the new origin. No customer touches anything and there’s no mass email campaign. The blast radius of the scariest step got shrunk before we took it.
  3. Nothing. The stack stays. If a piece of it ever earns a rebuild, it will be because the numbers say so, module by module, on a track that can be interrupted any time revenue work needs the capacity.

Running it alongside the business

None of this paused the business. Over the same months, we shipped product releases, because the migration work rides in the gaps. The edge cutover alone stretched across those months, with customer-managed domains chased down a few at a time. It was never a sprint that froze the roadmap. We run AI agents on several tasks in parallel, so infrastructure grinds forward in the background while revenue features hold the critical path. Five years ago that juggle wasn’t possible for a team our size, and “urgent infrastructure versus income” would have been a brutal either-or. Now it’s a scheduling problem.

We wrote down what the hardware deadline actually requires, and nothing else earned a spot on the list. Everything that tried to sneak on was discretionary work borrowing the deadline’s urgency, and left unchecked it turns an infrastructure crisis into a rewrite.

Where it stands

The origin sits behind the edge now. Customer-managed domains are still moving over a few at a time, and the hardware move hasn’t happened yet. The host’s timer is still running, and we’re spending the months before it fires shipping product releases. The stack replacement can wait for a deadline that actually asks for it.

If that turns out to be the wrong call, at least this time it will be wrong in a way we can point to on a spreadsheet, instead of three years of throughput we only understood in the rear-view mirror. Keep the hardware move separate from any decision to rewrite the software, put a stable layer in front first, and judge a rewrite on its own economics.