Rewrite vs. Refactor: Why We Almost Always Choose Incremental Modernization

Your platform is slowing your team down. Pages take too long to load, new features take weeks to ship, and every integration feels like open-heart surgery. A developer on your team suggests the obvious fix: "Let's just rewrite it."
It sounds clean. A fresh start. No more fighting legacy code. But for most companies running a live operations platform, a full rewrite is one of the riskiest decisions you can make. Software modernization does not have to mean starting over.
In over a decade of working with international clients, the team at NUS Technology has tackled this decision many times. The conclusion we keep coming back to: incremental modernization almost always wins. Here is why.
Why Full Rewrites Fail More Often Than You Think
The appeal of a clean rewrite is psychological as much as technical. The old codebase feels like a liability. But the numbers are not encouraging. Studies summarised in modernisation decision frameworks suggest that 60 to 80% of software rewrites either fail to deliver their expected benefits or are cancelled outright, and those that do succeed commonly take two to three times longer and cost more than projected.
That is not a fringe outcome. That is the norm.
The reasons are predictable. A rewrite requires two codebases running in parallel, doubling your maintenance overhead. Your team has to rebuild years of accumulated domain logic from memory and partial documentation. The edge cases you forgot about come back in production. And the business does not stand still while you rebuild.
For companies where the platform IS the operation, downtime is not acceptable. A booking platform going dark for six months. An order management system frozen while you migrate. These are not theoretical risks.
Joel Spolsky's famous diagnosis of Netscape's collapse still resonates: their decision to rewrite from scratch was described as "the single worst strategic mistake that any software company can make."
What Incremental Modernization Actually Looks Like
Incremental modernisation is not just "small refactors here and there." It is a disciplined, sequenced strategy for replacing your system module by module while keeping the lights on.
The most reliable execution pattern is sometimes called the strangler fig approach. You build the new implementation alongside the old one and route traffic to it gradually, strangling the legacy system piece by piece until nothing depends on it anymore.
In practice, this looks like:
- Start with a technical audit. Map the system's modules, identify the highest-risk areas, and document the business logic buried in the code.
- Draw hard boundaries between components. Define what each module owns and what it does not.
- Prioritise by impact. Which module, if replaced, would unlock the most downstream improvements? Start there.
- Replace one module at a time behind a stable interface. The rest of the system does not know anything changed.
- Validate in production before moving on.
This approach keeps your product live, your team learning, and your scope controlled. It also surfaces forgotten edge cases incrementally rather than all at once on launch day.
For companies looking at platform modernisation, this kind of sequenced approach is usually far less painful than the blank-slate alternative.
The Hidden Cost Nobody Talks About: Domain Knowledge
Here is the thing every dev shop glosses over when they pitch a rewrite: your existing codebase contains years of business logic that is almost impossible to fully document.
Every conditional you see in that ten-year-old Ruby on Rails codebase was written for a reason. A customer edge case. A compliance requirement. A fix for a bug nobody remembers. When you rewrite, you are betting that you can reconstruct all of it correctly.
You usually cannot.
One of our longest-running partnerships, with Your Best Grade, an EdTech platform for nursing exam preparation, is a good example of this. The platform had over 11 years of technical debt and 18 complex interactive question types. A rewrite of that scope would have meant rebuilding domain-specific logic accumulated over more than a decade, including complex payment flows and test timing logic that had been refined through thousands of real user sessions.
Instead, the team worked through it incrementally. A Redis caching layer was introduced to decouple question serving from the database. The Test Creator module, which was timing out at up to two minutes, was brought down to 3 to 7 seconds. Interactive question types were rebuilt in React component by component. The platform stayed live throughout. The partnership has continued for 8 years.
When a Rewrite Actually Makes Sense
Incremental modernisation is not always the answer. There are specific situations where a rewrite is genuinely the right call.
The clearest one: when the existing architecture physically cannot support where the business needs to go. If you are on a monolith that cannot be decomposed, if you are changing technology stacks entirely, or if the system is so undocumented that nobody understands what it does, the cost of incrementally untangling it may exceed the cost of replacing it.
A rewrite also makes more sense when:
- The platform is not live or not business-critical. A decommissioned internal tool, a prototype that never scaled.
- The business model has fundamentally changed and the old data model is completely incompatible.
- The team that built the original is entirely gone and there is zero institutional knowledge to preserve.
Even in these cases, the scope should be scoped tightly. A full rewrite of a massive platform is still a high-risk bet. Partial rewrites of well-defined modules are a different conversation.
How to Audit Before You Decide
Before committing to either path, do the analysis. Most teams skip this step and go straight to arguing about technology choices.
A solid pre-decision audit covers:
Performance profiling. Where are the actual bottlenecks? Is it queries, background jobs, memory, or architecture? You might be surprised how much headroom a targeted fix creates. When we audited HelpfulCrowd's infrastructure, the team found a PostgreSQL instance regularly hitting 100% CPU. Targeted query rewrites, index optimisation, and a move from AWS to Heroku cut infrastructure costs by 50% and doubled the feature release cycle, without a rewrite.
Module mapping. Which parts of the system are tightly coupled? Where are the natural seams? Understanding this tells you whether incremental replacement is feasible.
Domain logic inventory. Where does the business logic live? Is it in the application layer, in stored procedures, in worker jobs? Logic buried in unexpected places is what kills rewrites.
Team capability. Does your team have experience running parallel codebases? Have they done a migration of this scale before? Execution risk is as important as technical risk.
If you want help structuring this analysis, our Business Analysis and Strategy team has run this process across many industries and platform types.
The BikeBiz Case: Modernisation Without Starting From Scratch
When BikeBiz, one of Australia's leading motorcycle parts retailers, needed to escape a slow and inflexible Magento storefront, the team faced a genuine modernisation decision.
The core Magento system was showing its age. Mobile performance was poor, Core Web Vitals were failing, and the checkout experience was costing conversions. But the product catalogue, pricing logic, and order management were battle-tested and deeply understood.
Rather than scrapping everything, the team replaced the frontend layer with a headless Next.js and Saleor architecture while preserving the product data model and business rules. Server-side rendering, mobile-first UX, and progressive image loading were introduced without touching the core commerce logic unnecessarily.
The outcome: organic traffic up 35%, online revenue up 30%, and a 40% reduction in support inquiries. You can read the full breakdown in the case studies.
That is what targeted modernisation looks like in practice.
FAQ
How do I know if my codebase needs a rewrite or just a refactor?
Start with a performance and architecture audit rather than a gut feeling. If the system's architecture can support your next two to three years of product goals with incremental improvement, a refactor is almost always safer and faster. If the architecture itself is the ceiling and there is no way to add the abstractions you need, a partial or full rewrite may be justified. The key question is whether the existing structure can be incrementally evolved or whether it is a fundamental blocker.
How long does incremental modernisation take compared to a full rewrite?
Incremental modernisation delivers visible improvements within weeks or months because each module is replaced and deployed independently. A full rewrite typically takes significantly longer than estimated and nothing ships until it is done. For a mid-sized operations platform, a full rewrite that was scoped at six months often runs 12 to 18 months once forgotten requirements and integration complexity surface. Incremental work rarely suffers the same compounding delays because each phase is bounded.
What is the strangler fig pattern and is it right for my system?
The strangler fig pattern routes specific functions or modules to a new implementation while the old system handles everything else. Over time, more traffic is rerouted until the old system is no longer needed and can be removed. It works well when you have clear module boundaries and a stable API layer between components. It is harder to apply in tightly coupled monoliths with no defined interfaces, though refactoring to create those boundaries is usually a worthwhile first step.
Can you modernise a platform without disrupting live users?
Yes, this is the main advantage of the incremental approach. Modules are replaced behind stable interfaces, so users experience continuous operation with progressive improvement rather than a high-stakes cutover. The risk is lower, the feedback loop is faster, and the business keeps running throughout. This is particularly important for operations backbone platforms where downtime is not acceptable.
Conclusion
A full rewrite feels like the courageous call. It rarely is. For most live platforms, incremental modernisation is the more disciplined, more reliable, and ultimately faster path to a system your team can actually build on.
The goal is not clean code for its own sake. It is a platform that supports your operations today and can be extended without pain tomorrow. That is almost always achievable through a well-sequenced modernisation strategy, without the all-or-nothing gamble of starting from scratch.
If you are trying to decide which path makes sense for your platform, talk to the NUS Technology team. We have spent 12 years working through exactly these decisions with product teams across the US, Europe, and Australia.


