Skip to main content
Leeonex
All insights

Software project rescue

Refactor or Rewrite a Web Application? A Software Rescue Guide

A rescue-first framework for product and engineering teams deciding what to keep, what to repair in slices, and when a rewrite has actually earned its risk.

By Leeonex16 min read
Fragile module in a web application being isolated, verified, and replaced through a controlled incremental recovery path
A rescue decision should isolate the failing constraints and prove a safe migration slice before committing the whole product to a rewrite.

The short answer: rewrite only after the current system proves it cannot reach the target safely

Refactor when the product still fits the business, its behaviour can be verified, and important risks can be isolated behind workable boundaries. Replace selected subsystems when one dependency or capability is the constraint. Rewrite only when a measurable requirement cannot be reached responsibly on the current foundation—and the team can specify, verify, migrate, operate, and roll back the replacement.

The first rescue decision is often neither refactor nor rewrite. It is to pause avoidable feature scope, make production observable, restore a safe deployment path, and identify which business capability is actually failing. A framework that feels old is not the same as a system that cannot be recovered. A clean new repository is not evidence that old behaviour, data, integrations, and operational knowledge can be recreated.

Preserve

Working business rules, data, interfaces, and knowledge.

Stabilize

Incidents, deployment, observability, and critical journeys.

Change in slices

One bounded capability with verification and rollback.

Stabilize enough to make a trustworthy decision

A team deciding during an outage or missed launch will naturally overvalue a dramatic reset. Separate urgent containment from the modernization decision. Record active incidents, protect data, stop risky releases, and restore the smallest dependable path to deploy and roll back. Then gather evidence from the system while it still carries the real workload.

  1. Name the business-critical journeys. Identify the user and operator flows whose failure creates material harm, delay, or support load.
  2. Capture current behaviour. Use logs, traces, representative records, API contracts, screenshots, and stakeholder examples to expose what the application actually does.
  3. Restore a controlled release path. Document environments, configuration, migrations, smoke tests, deployment approval, rollback, and ownership.
  4. Verify security requirements. Turn the relevant controls into testable acceptance criteria rather than assuming that new code is secure by default. OWASP’s Application Security Verification Standard provides an open basis for specifying and testing web application security controls.
  5. Freeze the target. Define the measurable reliability, supportability, compliance, delivery, or product capability that the recovery must reach.

Missing documentation and tests raise the cost of every option. They do not automatically favour a rewrite. Characterization tests around critical behaviour, contract tests at boundaries, data reconciliation, and production observation may create a safer decision surface without first understanding every line.

Use a rescue matrix to expose the real pressure

Score each dimension from 0 to 2 using written evidence: 0 is healthy or controlled, 1 is constrained but investigable, and 2 is a severe blocker. Do not add the numbers and let the total decide. A single severe security, data, or platform-support constraint may carry more consequence than several maintainable annoyances.

Software rescue decision matrix rating business fit, production stability, change safety, platform support, data coupling, and migration testability
Score the evidence, then investigate every severe constraint. The matrix frames a rescue review; it does not automate the architecture decision.

The matrix is a Leeonex planning heuristic, not an industry benchmark. Beside every score, record the failing requirement, affected capability, available evidence, reversibility, and the smallest experiment that could change the decision. “The code is messy” is not yet evidence. “This unsupported runtime cannot receive required security updates, and the upgrade spike fails at these dependencies” is actionable.

Compare five recovery options capability by capability

OptionBest fitKey proofMain risk
RetainStable capability with low change demandSupported operation and acceptable riskNeglecting required maintenance
StabilizeIncidents or release process hide the real conditionObservable critical paths and safe deploymentTurning containment into permanent architecture
RefactorBehaviour is valuable and boundaries can be improvedTests, measurements, and reversible slicesEndless cleanup without a business target
Replace or replatformOne subsystem or platform is the constraintContract, data, and integration fitMoving hidden customization into workarounds
RewriteCore system cannot meet a necessary measurable targetVerifiable behaviour and funded migrationParallel operation, missing rules, and cutover exposure

The choice can differ across the same product. Retain a stable billing integration, stabilize deployment, refactor permissions, replace an unsupported search service, and rebuild one workflow behind a new boundary. This portfolio view prevents a local problem from becoming a whole-application rewrite.

Prefer incremental displacement when coexistence is possible

Martin Fowler’s original Strangler Fig Application describes gradually creating a new system around the edges of the old rather than relying on one high-pressure cutover. AWS and Microsoft both document versions of this pattern in which a routing layer sends a capability to either the legacy or new implementation while migration progresses.

Incremental application recovery map moving from observation and stabilization through a verified slice, controlled coexistence, and retirement
A safe recovery creates observable behaviour, stabilizes production, proves one boundary, and keeps rollback available while old and new paths coexist.

Incremental does not mean simple. The systems may need to share identity, data, events, and operational support. Microsoft’s architecture guidance calls out transitional infrastructure, cross-system dependencies, data-store coexistence, and the risk of a routing façade becoming a bottleneck or single point of failure. AWS’s prescriptive pattern similarly routes individual capabilities to old or new implementations. Use the idea only where requests or work can be separated and verified; a small, simple system may not need that extra architecture.

Prove one safe recovery slice before funding the programme

Choose one business capability that is valuable, bounded enough to isolate, and representative of a meaningful risk. Avoid the easiest static page if it teaches nothing about data, identity, integration, or release. Also avoid the most entangled transaction as the first experiment when no control surface exists.

  • State the current and target behaviour with accepted, rejected, boundary, and exception examples.
  • Map callers, downstream systems, data ownership, scheduled work, permissions, audit needs, and operational owners.
  • Define verification using contracts, representative records, side-by-side results, task completion, and production signals.
  • Decide how traffic or work enters the new path and how it returns to the old path if acceptance fails.
  • Record who can approve expansion, pause the slice, or retire old behaviour.

If the system mainly needs a specific new workflow rather than a broad recovery, compare the slice with Leeonex’s custom web application path. If operations are still defining the workflow in spreadsheets, the spreadsheet replacement decision guide helps determine whether the process is stable enough to encode before it becomes part of modernization scope.

A rewrite needs a business case and a migration case

A credible rewrite proposal names the target the old system cannot reach, the evidence supporting that conclusion, and the cost of doing nothing. It also explains how the business will operate while the replacement is incomplete. Continued fixes, regulatory changes, support, and feature commitments do not disappear because a new repository exists.

Require a capability inventory, data migration and reconciliation plan, integration contracts, security acceptance, operational readiness, phased release or cutover design, rollback, ownership, decommission criteria, and a scope rule for new features. If expected behaviour cannot be described or observed, budget discovery and stabilization first. Rewriting an unknown system creates a new implementation of an unknown requirement.

Leeonex’s software project rescue service starts with the codebase, incidents, scope, process, and decision owners, then produces a prioritized stabilization path. That review may support refactoring, selective replacement, or a rewrite; it is not designed to protect one answer in advance.

Once the recovery path is clear, use the legacy application modernization roadmap to turn that decision into a phased capability sequence with coexistence, data authority, rollback, and retirement gates.

Use the staff augmentation or project delivery guide to decide whether internal leaders should direct added capacity or a supplier should own a bounded delivery outcome.

Use this worksheet to define the first recovery slice

Complete it with the engineers and operators who know the live behaviour, plus the product or business owner who can decide scope. Attach real incidents and records where access permits. Mark assumptions, data sensitivities, and missing owners rather than filling gaps with confident language.

Software rescue slice worksheet covering business capability, current behaviour, dependencies, data ownership, verification, rollback, and completion rules
Define a recovery slice around one business capability with explicit evidence, dependencies, verification, ownership, and rollback.

A useful first slice ends with a decision: expand the pattern, adjust the boundary, retain the existing capability, replace a dependency, or stop the modernization path. “New code shipped” is not enough. The slice should improve confidence in behaviour, delivery, migration, and ownership while leaving production recoverable.

Refactor or rewrite FAQ

Is it better to refactor or rewrite a legacy web application?

Refactor when the product still fits the business, production behaviour can be observed, important components have usable boundaries, and the current platform has a responsible upgrade path. Consider replacement or rewrite when core requirements have changed, essential technology is unsupported, structural risks cannot be isolated, or the current system cannot reach a measurable target safely.

Should we rewrite an application because it has no tests?

No. Missing tests increase the risk of both refactoring and rewriting because expected behaviour is harder to verify. Start with production observations, critical user journeys, contract or characterization tests, data reconciliation checks, and a small change to learn whether the system can be controlled.

Can a web application be modernized without a full rewrite?

Often, yes. Teams can stabilize dependencies, upgrade in stages, isolate modules, introduce adapters, move one capability behind a controlled boundary, replace a subsystem, or use an incremental displacement pattern while the existing application continues to serve unmigrated behaviour.

When is a complete rewrite justified?

A rewrite is more defensible when there is a measurable target the current architecture cannot reach, the required behaviour and data can be verified, a safe coexistence or cutover plan exists, and the business can fund both migration and continued operation. Framework dislike or a desire for cleaner code is not enough.

What should a software project rescue review include?

Review business-critical flows, incidents, deployment and rollback, runtime and dependency support, security controls, test and observability coverage, data ownership, integrations, release process, documentation, product scope, and decision rights. The result should be a prioritized stabilization plan, not a generic technical-debt list.

Get an honest recovery path before funding a rewrite.

Bring the repository, current scope, known incidents, deployment reality, and the business capabilities that cannot fail. Leeonex can diagnose the blockers, define the first safe slice, and recommend retain, repair, replace, or rewrite without protecting a preferred answer.

Diagnosis before acceleration, production stability before new scope, and a rewrite only when the evidence supports it.