When to rebuild a web application, and when to refactor it
Rebuilds are proposed more often than they are justified, and the reasoning is usually aesthetic rather than economic. This is how to tell the difference, and how to do it in stages if the answer really is yes.
Refactor when the architecture can carry the next two years of changes and the problems are localised. Rebuild when the foundations block every change, when the platform is unsupported, or when the product's shape has diverged from what the system was designed for. Then replace it gradually, one capability at a time, rather than in a single release.
Signals that actually justify a rebuild
Every change is expensive in the same place. If the estimate for any new feature is dominated by working around the same structural decision, the structure is the cost and it will keep being the cost.
The platform is unsupported. An unmaintained framework or an end-of-life runtime is a security clock, and no amount of refactoring restarts it.
Nobody can safely change it. No tests, no documentation, and nobody left who worked on it. That is not a code-quality problem, it is an operational risk, and it means every change is a gamble.
The product has diverged. A system designed for one workflow and stretched across four does not have a refactor available; the model itself is wrong.
Notice what is not on this list: the stack being unfashionable, the code being ugly, and a new team preferring something else.
- The same structural decision dominates every estimate
- An unsupported platform or runtime
- No tests, no documentation, nobody who knows it
- The data model no longer matches the product
Why rebuilds go wrong
The existing system encodes years of decisions nobody wrote down: the edge cases, the customer-specific behaviours, the workarounds for a partner's broken API. A rewrite reproduces the visible features and rediscovers the rest one support ticket at a time.
The second problem is duration. During a rebuild, the old system still needs maintaining and the new one delivers nothing, so the business pays twice and receives nothing new for however long it takes. That period is always longer than the estimate, because the estimate was made from the visible features.
The third is that the reasons for the rebuild often survive it. A team that produced an unmaintainable system under the same pressures, with the same constraints and the same deadline, frequently produces another one.
Replacing it gradually
The pattern that works routes traffic for one capability at a time to new code while the old system keeps serving everything else. The new implementation grows around the old one until nothing is routed to it, and it is switched off.
Concretely: put something in front that can route per path or per feature, move one bounded capability, run both against real traffic, then move the next. Each step ships value and each step is reversible.
It is slower in total than a clean rewrite would be if a clean rewrite ever went to plan. What it buys is that you can stop at any point and still be better off, and that you find the undocumented behaviour one capability at a time instead of all at once on launch day.
Start with the capability that is causing the most pain and has the clearest boundary. Resist starting with the one that is most fun.
Protecting what the old system earned
Search traffic is the asset most often destroyed by a rebuild, and always by the same mistakes. Inventory every URL with its traffic and rankings before anything changes, map each one to its destination, and redirect with permanent redirects to the specific equivalent page rather than to the homepage.
Keep the content that earns traffic. Simplification during a redesign routinely deletes the pages that were actually bringing people in, because they were not the pages anyone in the room cared about.
Watch out for the new stack rendering nothing without JavaScript, and for a staging site left indexable while the live one is accidentally excluded. Both are common and both are self-inflicted.
Verify coverage after launch rather than assuming it. A drop takes weeks to appear in reporting and longer to recover from once it has.
- Inventory URLs and their performance before changing anything
- Redirect to the specific equivalent, not the homepage
- Keep the content that earns the traffic
- Check coverage after launch instead of assuming
What an assessment should produce
A recommendation with reasoning, not a verdict. Where the risk actually is, what a refactor would cost against what a staged replacement would cost, and what happens if you do nothing for another year.
We would rather run that assessment and recommend targeted improvements than sell a rebuild. A rebuild proposed without one is a proposal about our preferences rather than your constraints.
And if the honest answer is that the system is fine and the problem is the deployment process, or the test coverage, or one badly modelled table, that is a much cheaper piece of work and we will say so.
Questions people also ask
How do you know if a rebuild is worth it?
Compare the cost of the next two years of changes under the current architecture against the cost of replacing it plus the delivery you forgo during the replacement. If the same structural decision dominates every estimate, the arithmetic usually favours replacement. If the problems are localised, it does not.
Will a rebuild hurt our search rankings?
It can, and the damage is nearly always self-inflicted: dropped URLs without redirects, deleted content that was earning traffic, a new stack that renders nothing without JavaScript, or a staging site left indexable. Each is avoidable with an inventory and a redirect map made before anything changes.
Can you rebuild part of a system?
Yes, and it is usually the right approach. Route one capability at a time to new code while the old system keeps serving the rest, until nothing is routed to it. Each step ships value and each step can be reversed.
How long should an assessment take?
Typically one to two weeks for a system of moderate size: reading the code, reviewing the dependency and hosting situation, looking at analytics and error rates, and talking to whoever maintains it. It should end with a recommendation and reasoning, not a verdict.