Seven paths, what each one actually changes, and the refactor-or-rewrite decision that determines the budget.
Disclosure. legacymodernizationhub.com is operated by Chudovo OÜ. Cost and timeline figures in this guide are the ranges Chudovo publishes from its own delivered projects. They are one vendor’s reference points, not industry averages. Frameworks cited inline come from AWS, Microsoft and Martin Fowler.
This is an application-level decision
Portfolio strategy decides which systems get budget. This guide covers what happens next: you have one application, it is worth investing in, and you need to choose a path.
The paths are not interchangeable. They differ by a factor of twenty in cost and they change different parts of the system — which is why picking by preference rather than by diagnosis is the most expensive mistake available here.
The seven paths
The taxonomy comes from AWS, documented as the “7 Rs” in its prescriptive guidance; Microsoft covers equivalent ground in the Cloud Adoption Framework. Applied to one application:
Why retire and repurchase lead. Both remove the problem instead of solving it, and both are routinely skipped because the conversation starts with “how do we modernize this” rather than “should this exist”. An application nobody has used meaningfully in two years does not need a strategy; a payroll system does not need to be custom.
What each path actually changes
The paths are often presented as a ladder of increasing effort, which hides the more useful fact: they change different layers. A team that rehosts because “we need to modernize” has not touched the layer their complaint came from.
Refactor, reengineer or rebuild
For applications in the bottom branch — where the code is the problem — the real decision is how far to go. Three terms get used interchangeably and mean different things:
Refactoring changes the internal structure of existing code without altering external behaviour. The application does the same things; it becomes testable, modifiable and comprehensible. This is the default answer and the cheapest.
Reengineering goes further: changing the technology stack, reworking the data model, rebuilding specific components. The work starts as refactoring and escalates where refactoring is not enough.
Rebuilding replaces the application from scratch, preserving business logic but not the implementation.
The test for a rebuild
A rewrite is justified when you need to change the application and cannot use the existing codebase at any price. That condition is rarer than it is claimed to be. Most “we have to rewrite” arguments translate to “the codebase is unpleasant”, which is an argument for refactoring.
Before committing to a rebuild, three checks:
- Is the business logic documented anywhere other than the code? If not, a rebuild means rediscovering years of accumulated rules — usually from production incidents after launch
- Can the old and new systems run in parallel? If not, you are planning a big-bang cutover, which is where rewrites fail
- Is the team that will rebuild it the team that understands it? A rewrite by people who did not maintain the original reproduces the original’s bugs and adds new ones
If a rebuild survives all three, it is probably the right call. Most do not.
Signs refactoring is what you need
- Adding a simple feature means touching code in several places that should not be connected
- The team avoids certain sections because the consequences are hard to predict
- Finding bugs is slow because the logic has no clear separation
- Onboarding takes weeks due to missing or wrong documentation
- Tests are slow, flaky or skipped because they are too delicate to maintain
- Builds and deployments need manual fixes to complete
These describe an application that works but cannot be worked on — the exact case refactoring addresses.
How refactoring is delivered without stopping the business
The application stays live. That is a requirement, not a nice-to-have: an engagement that needs a feature freeze has quietly become a rebuild.
Audit first, scope second. A technical audit establishes the level of technical debt, which areas carry it, and the order to address them. Estimates produced without this are guesses.
Incremental delivery. Work proceeds in phases while production runs. Each phase is verified before the next begins, which leaves room to adjust the approach after the first contact with reality.
Feature flags where needed. New paths run alongside old ones, traffic shifts gradually, rollback is immediate. The same mechanism as Martin Fowler’s Strangler Fig pattern applied at a smaller scale.
Business logic preserved explicitly. The rules, calculations and workflows the organization depends on are the asset. The implementation is not.
Cost and timeline
Published ranges from Chudovo for application refactoring:
| Application scope | Duration | Cost |
|---|---|---|
| Small, limited scope | 2–4 weeks | $5,000–$10,000 |
| Mid-sized, several modules, some test coverage | 1–3 months | $15,000–$25,000 |
| Large enterprise: distributed components, no test coverage, regulatory constraints | 3+ months | from $30,000 |
Read what sets the tiers: module count, existing test coverage and regulatory scope — not lines of code. An application with 200,000 lines and a working test suite is a smaller job than one with 60,000 lines and none.
For comparison, the same work at other depths: architecture-level modernization of a mid-sized system runs 3–6 months, and a large enterprise system 6–18 months. A full rebuild is a different budget conversation entirely, which is the practical reason the three-check test above matters.
Where application modernization goes wrong
The path was chosen before the diagnosis. “We’re moving to the cloud” is a decision about hosting that gets applied to applications whose problems are in the code.
Rehosting was sold as modernization. The application runs in a new place and behaves identically, including the three-week lead time that prompted the project.
A rewrite was chosen because the codebase was unpleasant. The three checks above exist because this is the most expensive mistake in the list.
The audit was skipped. Scope set from a walkthrough and a few opinions. Every subsequent estimate inherits the error.
Refactoring had no end condition. Without a defined target — coverage threshold, specific modules, measurable lead time — refactoring expands until the budget runs out, and the business sees no deliverable.
Business logic was not separated from implementation. In a rebuild especially, this is what gets lost: rules that existed only in code, rediscovered through production failures.
Measuring it
Baseline before, measure after:
- Lead time from merge to production
- Change failure rate
- Defect rate in the modernized areas
- Test coverage in the areas touched
- Onboarding time to first meaningful commit
Published averages across Chudovo engagements: 30–50% faster feature delivery, 25–40% less time on bug fixing and maintenance, 30–60% lower defect rates, and test coverage moving from near-zero to 60–80%. These are averages across projects — useful for sanity-checking a business case rather than for forecasting yours.
FAQ
What is the difference between refactoring and rewriting? Refactoring changes the internal structure of existing code without altering external behaviour. A rewrite rebuilds the application from scratch. Refactoring is the safer option when existing code can still be worked with; a rewrite is necessary only when the codebase cannot be used at any price — a condition that is rarer than it is claimed.
What is the difference between refactoring and reengineering? Refactoring improves the codebase without affecting functionality. Reengineering may change the technology stack, rework the data model, or rebuild specific components. Projects usually begin as refactoring and escalate where refactoring is not enough.
Does the application stay live during refactoring? Yes. The work runs in parallel with active development, using feature flags where new paths need validation. An engagement that requires a freeze should be evaluated as a rebuild.
How long does application refactoring take? Two to four weeks for a small application with limited scope. One to three months for a mid-sized application with several modules and some test coverage. Three months or more for large enterprise applications with distributed components, no coverage and regulatory constraints.
Is rehosting a form of modernization? No. Rehosting changes where the application runs. If the complaint is about development speed, defect rates or maintainability, rehosting will not address it.
Which path is cheapest? Retire, then retain. Both are routinely overlooked because the conversation starts with how to modernize rather than whether to.