Rescue or Rewrite? How to Decide What to Do with a Failing Software Project

September 21, 2026 Project Rescue Team @ Lionasys Project Rescue
Decision between rescuing and rewriting a failing software project

In our experience, most failing software projects should be rescued, not rewritten. If the data model is sound and a new developer can build, deploy, and test the system, it is nearly always faster and safer to repair what exists, even when the code is ugly. A full rewrite is justified when the foundation itself is broken: the framework is no longer supported, there are no tests and no practical way to add them, and the data model misrepresents the business so badly that every feature fights it.

Between those two sits a third option that we recommend more often than either, which is replacing the system one module at a time while it keeps running. The rest of this article explains how to tell which case you are in and how to check the advice you are given.

Why a Full Rewrite Is Tempting and Usually Underestimated

Reading someone else's code is harder than writing your own, so almost every developer who inherits a messy system feels the pull to start again. The rewrite estimate then gets built from the visible features, and it comes out too low for three reasons.

The first is hidden business rules. Old code is full of small conditions that look like clutter, such as a special tax case for one region, a rounding rule an accountant insisted on, or a workaround for a partner's API that sends dates in the wrong format. They appear in no specification. The old code is the only record, and a rewrite drops them until customers complain.

The second is what engineers call the second-system effect. A team freed from the old constraints designs the replacement to handle everything the first version could not, and the scope grows.

The third is that you run two systems at once. The old product still needs bug fixes and the occasional urgent feature while the new one is built, so you pay for both, and the new system chases a target that keeps moving. Data migration from a messy schema, which comes at the end, is a project of its own.

What an Honest Audit Examines

These are the things we look at, roughly in order of how much they sway the decision.

The Data Model

This carries the most weight. We look at whether the tables describe the business correctly, whether the database enforces integrity through foreign keys and constraints, and whether the stored data is clean. Code on top of a sound data model can be replaced a piece at a time. When the model is wrong, every screen and report built on it inherits the problem, and fixing it means migrating live data, which is the riskiest work in any rescue.

Whether a New Person Can Build, Deploy, and Test It

We try to get the system running on a clean machine from the repository alone, then try to deploy it to a staging environment. If that takes a day, the project is in better shape than its reputation suggests. If nobody can reproduce the production build, that needs to be solved before anything else, whichever route you choose.

Tests and Testability

Few troubled projects have good automated tests. The more useful thing to establish is whether tests can be added. Code with business logic separated from the user interface and the database can be put under test gradually. Code where a single function reads the request, queries the database, and renders the page is much harder to test, so every change to it is a gamble.

Dependency and Framework Age

We list the language version, the framework, and the major libraries, and check which are still receiving security updates. Being a few versions behind is routine. Being on a framework whose maintainers have stopped releasing fixes is different, particularly when the upgrade path crosses several breaking major versions or does not exist at all.

Security Posture

The checks are basic ones: how passwords are stored, whether secrets are committed to the repository, whether database queries are parameterized, how access control is enforced on the server, and whether dependencies carry known vulnerabilities. Individual holes can be patched, but a design with no server-side access control points to deeper trouble.

Architecture Against the Roadmap

Architecture only has to be good enough for what you plan to build. A single-server monolith is fine for many products. We compare the structure against the next year or two of the roadmap, not against an ideal.

What the History Shows

The commit history shows how the previous team worked. We look at whether changes were small and described, whether there was any code review, and whether fixes addressed causes or patched symptoms. Careful work under deadline pressure suggests the code is better than it looks, while large unexplained commits and commented-out blocks suggest more surprises are waiting.

Signals That Favor Rescue

A sound data model under a messy interface is the classic rescue case. So is a system that works but is slow, because performance problems usually trace to a handful of queries and missing indexes. Others include a supported framework that is a few versions behind, and bugs concentrated in two or three modules while the rest is stable. Code that is merely unpleasant to read belongs here too, since style is cheap to fix.

Signals That Favor a Rewrite

The case for rewriting gets strong when several of these hold at once: the framework or platform is unsupported with no upgrade path, there are no tests and the structure prevents adding them, the data model is wrong at its core and the stored data is already inconsistent, and nobody can reproduce the build. A change of platform that makes the old code irrelevant also qualifies, for example moving from a desktop application to a web product.

Size matters as well. A small application with a clear specification can be rewritten at modest risk. For a system that took years to build, we would want each of the signals above confirmed before backing it.

The Middle Path: Replacing One Module at a Time

Incremental replacement, often called the strangler fig pattern, keeps the old system running and routes traffic through a stable interface such as a reverse proxy or an API gateway. You pick one module, build its replacement behind that interface, switch the route over, and watch it in production. Then you pick the next, until the old code can be switched off.

The advantage is that every step ships and can be reversed. There is no single cutover day on which everything has to work. We usually start with a module that is both painful and well bounded, such as reporting or notifications, and leave the tangled core until the team knows the domain.

It has costs. For a while you run two technology stacks and a routing layer, and both sides often share one database, which limits how much the schema can change until late in the process. It also takes discipline to finish, because a migration that stops halfway leaves you with two systems to maintain.

Keeping the Business Running

Whichever route you choose, a few things come first. Get working backups and a tested restore. Get a staging environment that matches production. Add error monitoring, so that you hear about failures before a customer reports them. Put basic automated tests around the flows that earn money, such as checkout and billing, before changing anything near them.

Then fix what is hurting customers this week, in small releases. During a rewrite, freeze new features on the old system except for what the business cannot live without, and say so explicitly to everyone who might ask for one. During a rescue, refactor only the code you need to touch.

How Do You Sanity-Check the Recommendation?

A vendor who recommends a rewrite stands to earn more from it, and a vendor who recommends a rescue may be underestimating the mess to win the work. Either way, ask for the evidence. A credible recommendation names specific files, tables, and dependencies, and explains what was tried. "The code is bad" is an opinion, while "the orders table stores line items as a text field, and here are the three reports that are wrong because of it" is a finding.

Ask what would change their mind. Ask for a first milestone that ships to production within a few weeks, because a plan whose first visible result is many months away resembles the one that already failed. For a rewrite, ask how the hidden business rules will be found and how data will be migrated, and expect a detailed answer. If the stakes are high, pay for a second opinion from someone who will not get the build work.

Common Mistakes

The one we see most is deciding on emotion. After a bad year with a vendor, everything they touched feels contaminated, and throwing it all away feels like progress. The quality of the code is a separate matter from the quality of the relationship, and it deserves to be judged on evidence.

Others are rewriting without first writing down what the old system does, underestimating data migration, and switching technology stack because the new team prefers it when the old stack is still supported. A rescue has its own trap, which is patching symptoms indefinitely without fixing the two or three structural problems that keep producing them.

Lionasys Technologies has been taking over software, AI, IoT, mobile, and game projects from Ahmedabad, India since 2010. Our initial rescue audit is free and takes one to two days, and a written recovery plan follows in three to five days with the evidence behind whichever route we recommend. Rescues typically run two to twelve weeks, under a no fix, no fee guarantee. If you are weighing this decision, get in touch and we will look at the code with you.

Tags:Project RescueSoftware RewriteCode AuditLegacy CodeTechnical DebtStrangler Pattern