The question usually comes up when things are already painful. Releases take three weeks, incidents keep climbing, engineers are updating their resumes, and someone suggests starting over. Starting fresh sounds clean, but without a clear way to evaluate trade-offs, it is one of the riskiest decisions a team can make.
Why the Question Is Hard
Rewrites fail often, and usually for the same reasons. The existing system holds years of undocumented business logic and edge cases. The replacement takes twice as long as planned. Requirements shift mid-project. When the new system finally launches, it introduces new bugs, while the developers who understood the original behavior have already moved on.
Joel Spolsky wrote about this in 2000, and his observation holds up well: existing code, however messy, represents years of bug fixes, edge cases, and hard-won domain knowledge. You lose all of that the moment you throw it away.
At the same time, incremental modernisation is not always the right choice. Some systems sit on foundations so broken that working around them costs more than starting clean. The challenge is figuring out which situation you are in.
Four Questions That Matter Most
1. What is the cost of the current system?
Before deciding anything, you need a clear picture of what the current system costs. That goes beyond hosting bills:
- Development velocity: How long does it take to ship a feature that should take a week?
- Incidents and recovery: How often does the system break, and how long does it take to fix?
- Onboarding cost: How many months before a new hire can push code safely?
- Opportunity cost: What features are you delaying because the team is stuck maintaining old code?
These numbers are hard to pin down precisely, but rough estimates give you enough signal. If a system cuts delivery speed in half, it doubles your engineering costs.
2. Where is the problem concentrated?
Systems that feel completely broken often have most of their pain concentrated in a few areas. Version control history usually confirms this: 80% of bugs and changes touch the same 20% of files. Those files are your complexity hotspots.
Ask whether the issue is architectural across the whole application or isolated to specific unmaintainable modules. If the problem is isolated, targeted modernisation by extracting or replacing those specific components carries lower risk and delivers most of the value.
3. What would you rebuild, and how long would it take?
Rewrite estimates are almost always wrong in the same direction. Teams estimate based on visible features, documented requirements, and happy paths. They miss the undocumented business rules buried in stored procedures, the edge cases in awkward-looking code, and integrations with third-party systems that still handle live traffic.
A practical check: take your estimate, write down every assumption behind it, and spend a week auditing the codebase against those assumptions. The timeline will grow quickly.
4. Can you run two systems in parallel?
The safest approach runs the new implementation alongside the existing system, shifting traffic gradually. This is the Strangler Fig pattern. It works well, but it demands engineering capacity to maintain two systems at once, routing infrastructure, and a way to verify behavioral parity.
Teams that attempt a single cutover date, building the replacement in isolation and switching overnight, take on enormous risk. Without a gradual feedback loop, rolling back means discarding months of work.
The Decision Framework
| Signal | Suggests Modernise | Suggests Rewrite |
|---|---|---|
| Architecture | Pain is concentrated in specific modules; rest of system is stable | Core design assumptions are incorrect throughout the system |
| Technology | Running on supported frameworks; migration path is clear | Platform is end-of-life with no upgrade path; vendor lock-in to discontinued product |
| Knowledge | Business domain is well understood; experts still available | Original developers gone; no documentation; behaviour understood only through production observation |
| Testing | Some test coverage exists; new tests can be written to protect migration | Zero test coverage; impossible to verify equivalence without running both systems against real traffic |
| Scale | Current architecture can scale with targeted changes | Scalability limits block business growth regardless of tuning |
| Team capacity | Team can allocate sprint capacity to modernisation work alongside features | Team has capacity to run both systems in parallel; rewrite timeline is realistic |
When Modernisation Is the Right Choice
Most projects fall into this category. The system has structural flaws, but you can fix them step by step. Using the Strangler Fig pattern, you place a reverse proxy like YARP in front of the application and replace routes one by one. Each new component gets clean architecture, proper tests, and modern dependencies without forcing a risky all-or-nothing release.
The hard part is discipline in sequencing. Start with the modules causing the most operational pain. Test each migrated piece thoroughly before tackling the next, and keep the application deployable throughout. Early progress feels slow, but within a few months the velocity gains become obvious.
When a Rewrite Is the Right Choice
Rewrites make sense in a few specific scenarios. The clearest case is when the underlying data model is completely wrong for the business, and the database relationships cannot be untangled incrementally. Another common trigger is an obsolete technology stack with no supported upgrade path, where keeping dependencies running consumes unreasonable effort.
If you decide to rewrite, apply the same staged discipline: split the work into milestones, ship usable parts early, keep the legacy system running in parallel, and verify behavior against live production traffic before retiring the old code.
Getting an Objective View
People closest to the system usually hold the strongest opinions. Developers who spend every day wrestling with technical debt want to start fresh. Business leaders who remember past project delays resist any talk of a rewrite. Both viewpoints come from real pain.
An outside technical assessment helps bridge this divide. It evaluates where the bottlenecks sit, measures system health, and lays out pragmatic paths forward based on evidence rather than frustration.
Our Software Architecture Assessment helps teams make this decision through an evaluation of application structure, code health, delivery pipelines, and infrastructure, paired with a practical roadmap. You can view our example report to see what the assessment delivers.