Somewhere past year five, almost every platform starts collecting complaints. Deploys feel risky, new features take twice as long as they used to, and at least one engineer has quietly suggested starting over. The question operators eventually type into a search bar, should I rebuild or refactor legacy software, is really a business question wearing a technical costume: how do we keep shipping without betting the company on a rewrite?
The honest answer is that it depends on signals you can actually check, not on how frustrated your team feels this quarter. This guide walks through those signals, the rare cases where a rebuild genuinely wins, and the strangler-fig migration pattern that is usually the right answer for a system people depend on every day.
Why the full rewrite is usually a trap
Rewrites fail for a predictable reason: the old system keeps running, and keeps changing, while the new one is being built. Customers do not pause their feature requests because your engineers are busy recreating what already exists. So the team either freezes the old platform (and watches the business stall) or maintains two systems at once (and watches the rewrite stall).
There is a second, quieter problem. A legacy codebase is full of business rules nobody remembers writing. Which order statuses allow a refund. How tax rounding works for one specific region. The edge case added after an angry customer call in 2019. A rewrite estimate covers the features everyone can name. It rarely covers the decisions buried in conditionals, and those are often the parts that keep revenue safe.
None of this means rewrites are always wrong. It means the burden of proof sits on the rebuild, not the refactor.
Signals that favor refactoring
Refactoring means improving the system you have, incrementally, while it keeps serving customers. It is the right call when most of these are true:
- Revenue depends on it daily. If orders, bookings, or payments flow through the platform every hour, any approach that takes it offline or freezes it is a direct business risk.
- The logic is the moat. Pricing engines, matching algorithms, scheduling rules refined over years: if the code encodes your competitive advantage, rewriting it means rediscovering it, usually in production.
- The framework is alive. An older version of a maintained framework is a cleanup project. You can upgrade in steps.
- Problems are localized. A slow reporting module or a tangled checkout flow is a surgical target. You do not demolish a house because one bathroom leaks.
- Someone still understands it. Institutional knowledge is an asset that a rewrite throws away on day one.
When these hold, the frustration people feel is usually about specific hot spots, not the whole system. Fix the hot spots.
Signals that genuinely favor a rebuild
Some platforms really are past saving, and pretending otherwise burns years. The case for a rebuild gets strong when several of these stack up:
- The framework or language is dead. No security patches, a shrinking hiring pool, and libraries that no longer receive updates. You are not maintaining software at that point, you are curating a museum with a login page.
- There are no tests and every change breaks two things. Without a safety net, refactoring is just rewriting in slow motion with extra fear. If adding a field to one form takes down an unrelated report, the coupling may be beyond incremental repair.
- The architecture fights the business model. A single-tenant system trying to serve a multi-tenant SaaS business, or a platform you rent that will not let you touch the code at all, cannot be refactored into something it was never allowed to be.
- Compliance cannot be retrofitted. Some security and data-handling requirements demand structural properties the original design simply lacks.
Notice what is not on this list: ugly code, an unfashionable stack, or a new CTO's preferences. Those are reasons to refactor, or reasons to do nothing.
The strangler fig: usually the right answer
Most real systems show mixed signals, which is why the best answer is often neither a pure refactor nor a big-bang rebuild. The strangler-fig pattern, named after the tree that grows around a host until it can stand alone, replaces a legacy platform piece by piece while it keeps running.
In practice it looks like this:
- Put a routing layer in front. All traffic passes through a facade you control, so you can send individual pages or endpoints to new code one at a time.
- Carve out one module. Start with something valuable but contained, then move its logic, its data, and its traffic. Ship it, watch it, move on.
- Migrate data in chunks, in the background. Customers, orders, and product records move through queued jobs that can be resumed and audited, never through one heroic overnight script.
- Protect the seams. Map every old URL to its new home, and log every 404 the old system would have served so missing redirects surface as a worklist instead of lost traffic. On a commerce platform, skipping this step quietly destroys years of accumulated search ranking.
- Externalize the rules first. Pull business rules like which order statuses allow cancellation out of code and into configuration before you move the code. Rules that live in config migrate cleanly and stop depending on anyone's memory.
The strangler approach costs more coordination than a rewrite on paper. In exchange, revenue never stops, rollback is always possible, and you learn the system's hidden rules one module at a time instead of all at once in a launch-week crisis.
How to run the decision in two weeks
Treat this as an audit, not a debate. Four checks produce most of the signal:
Count the deploys. How often does the team ship, and how often does a deploy cause an incident? A system shipped weekly without drama is healthier than it looks.
Check dependency lifespans. List the framework, language runtime, and top libraries against their end-of-life dates. This is the most objective input you have.
Measure the safety net. Not test coverage percentage, but a simpler question: can an engineer verify a change without manually clicking through the app? If not, your first investment is tests, whichever path you choose.
Interview the person who fears deploys. Ask them to name the three scariest areas. Those answers are either your refactoring targets or your first strangler modules.
If the audit says the core is sound, refactor the hot spots. If it says the foundation is gone, rebuild, but still do it strangler-style rather than as a parallel moonshot.
What maintaining 50+ products taught us
ETREXIO is a small studio, two senior builders working with an AI workforce where humans review every decision, and we currently maintain more than fifty shipped products. That portfolio has taught us something that reframes this whole question: most codebases people call unmaintainable are really under-documented. The code works. What is missing is the record of why it works that way, and a rewrite deletes the code while keeping the amnesia.
It has also taught us to be suspicious of rebuilds as scope-creep vehicles. "While we are rewriting it anyway" is the most expensive phrase in software, because it converts a migration into a product redesign with no finish line. Our client relationships average around five years, long enough to see that the platforms which thrive are the ones improved continuously, not replaced heroically.
If you are weighing this decision for your own platform and want a second opinion on the audit, talk to us. We will tell you honestly if the answer is to do less than you planned.
Frequently asked questions
When is a full rewrite of legacy software worth it?
A rewrite makes sense when the foundation is unrecoverable: the framework is end of life with no security patches, there is no test coverage so changes routinely break unrelated features, or the architecture structurally blocks the business model. Even then, a phased strangler-style rebuild carries far less risk than a parallel big-bang replacement.
What is the strangler fig pattern in software migration?
The strangler fig pattern replaces a legacy system incrementally. A routing layer sits in front of the old platform, and individual modules are moved to new code one at a time, with data migrated in background chunks. The old system keeps serving everything not yet replaced, so there is no risky cutover moment.
How long does refactoring a legacy platform take?
Refactoring is continuous rather than a single project, but meaningful results usually arrive module by module within weeks, not years. The sequence matters more than the total duration: add tests around the scariest areas first, externalize business rules into configuration, then restructure code behind those safety nets at a steady pace.
How much does it cost to modernize legacy software?
Cost depends on scope, data volume, and how many hidden business rules the system contains, which is why fixed-price rewrites so often overrun. Studios like ETREXIO work on monthly retainers, starting at $5,000 per month, which fits incremental modernization well because work ships continuously instead of accumulating toward one risky launch.