One of the harder conversations we have with clients is about whether to fix what exists or start again. It's harder than it sounds, because both options carry risks that are easy to underestimate from the outside.
The case for rebuilding is usually emotional as much as it is technical. There's something appealing about the idea of starting clean — no legacy constraints, no accumulated shortcuts, no code that nobody fully understands anymore. And sometimes that's genuinely the right call. If the existing system is so tightly coupled that making any change requires touching everything, or if the data model is so far from the current reality of the business that every feature is a fight against the structure, the cost of repairing may actually exceed the cost of rebuilding.
But rebuilding is rarely as clean as it sounds. The existing system, however messy, does things. Some of those things are documented. Many aren't. They're encoded in the behaviour of the system — the edge cases it handles, the implicit rules it enforces, the workflows it supports that nobody quite remembers agreeing to but that everyone now depends on. A rebuild that starts from a spec tends to rediscover these things slowly and painfully, often in production.
What we typically recommend is something more incremental. Rather than a binary choice between rebuild and repair, we look for the parts of the system that are causing the most constraint and ask whether those specific pieces can be addressed without touching everything else. A poorly designed data model can sometimes be wrapped rather than replaced. A slow query can often be fixed without restructuring the service around it.
The rebuild conversation usually comes up because something has become painful enough that people want it to stop. That pain is real and worth addressing. But "start again" isn't always the fastest way to stop it.