October 8, 2026

Legacy App Modernization: Replacing Software That Still Works

Legacy software is not software that is old. It is software that is difficult to change, and the two are not the same. A ten-year-old system with tests, documentation, and a sane architecture is...

Blog Image

Key takeaways from the blog

  • Legacy software is software that is difficult to change, not software that is old. A ten-year-old system with tests and documentation is not legacy, while a three-year-old system nobody dares modify is.
  • Name the actual problem before choosing a remedy: nobody can change it safely, the technology is unsupportable, it cannot do what you now need, it costs too much to run, or it is a compliance liability. Projects that skip this step tend to rebuild the visible interface and leave the real problem in place.
  • Buy a code audit before deciding anything. At $5,000 to $25,000 over one to three weeks, it should include remediation effort estimates and stated reasoning so the recommendation can be interrogated rather than simply accepted.
  • There are four paths, each priced relative to a rebuild: rehost at 10 to 25 percent, refactor at 20 to 50 percent, incremental replacement at 70 to 110 percent, and full rebuild as the baseline. Rehosting solves cost and supportability but does nothing for changeability.
  • Incremental replacement is usually the right answer because the product keeps working and you learn between steps. Its main protection is preserving the undocumented business rules the old system encodes, which is where full rebuilds most often fail.
  • Data migration is routinely 10 to 20 percent of a replacement build and absent from most initial estimates. Sequence the programme as stabilise, add tests, create a seam, replace the highest-pain area, and stop when the rest is good enough, while reserving 20 to 30 percent of capacity for roadmap work.

Legacy software is not software that is old. It is software that is difficult to change, and the two are not the same. A ten-year-old system with tests, documentation, and a sane architecture is not legacy. A three-year-old system nobody dares modify is.

That distinction matters because it identifies what you are actually solving. Modernisation projects that begin from age rather than from difficulty tend to replace working software with newer software that is equally hard to change.

Establish what is actually wrong

Five distinct problems get described as legacy, and each has a different remedy.

Nobody can change it safely. No tests, no documentation, original author gone, and every change breaks something unrelated. This is the practical definition and the most common.

The technology is unsupportable. An abandoned framework, a language version past end of life, or a dependency with no maintained successor. This is a genuine forcing function with a deadline attached.

It cannot do what you now need. Single-tenant where you need multi-tenant, no API where you need integration, no mobile where the work happens in the field. An architectural mismatch rather than a quality problem.

It costs too much to run. On-premise hardware, per-seat licensing on a platform you have outgrown, or infrastructure that scales badly.

It is a compliance liability. No audit logging, weak access control, unencrypted data, and an enterprise customer or regulator about to notice.

Write down which of the five applies. Projects that skip this step tend to rebuild the interface, which is the visible part, while leaving the actual problem in place.

Buy an audit before deciding anything

The modernisation decision is routinely made by whoever is in the room. The developer who inherited the code says rebuild, because unfamiliar code always looks worse than code you wrote. The firm quoting the rebuild agrees, because a rebuild is a larger engagement than a refactor.

A code audit replaces that with evidence: architecture assessment, test coverage, security findings, dependency currency, and, most importantly, whether the existing codebase can support your actual roadmap. It costs $5,000 to $25,000 over one to three weeks against a decision that routinely involves six figures.

Bolder Apps sells code audits as a standalone engagement, and the practical guidance for any firm you use is to require that the report includes remediation effort estimates and stated reasoning, so the recommendation can be interrogated and taken to other bidders rather than simply accepted.

Four modernisation paths

PathWhat it meansCost relative to rebuildRisk
RehostMove to modern infrastructure, code unchanged10 to 25 percentLow
RefactorImprove the code in place, behaviour unchanged20 to 50 percentLow to moderate
Incremental replacementReplace piece by piece behind a boundary70 to 110 percentLow, spread over time
Full rebuildNew system, cut overBaselineHigh

Note that rehosting solves cost and supportability problems and solves nothing about changeability. It is frequently a sensible first step that buys time rather than a modernisation in itself.

‍


Frosted strangler vines of glass wrapping a block

‍

Incremental replacement, which is usually the right answer

The approach that gets skipped because it is less satisfying than a clean rebuild: keep the existing system running and replace it in pieces.

A new component takes over one area of functionality. Traffic for that area routes to the new component. The old code for it is retired. Repeat with the next area. The product keeps working throughout, each step delivers value independently, and you can stop when the remaining old system is good enough.

The precondition is a seam you can substitute behind: an API boundary, a service boundary, or a module boundary. If none exists, creating one is the first piece of work rather than a reason to abandon the approach.

What this buys you is optionality. A rebuild requires being right about everything before you start and delivers nothing until cutover. Incremental replacement lets you learn between steps, which matters because your understanding of the requirements will change as you go.

The largest risk in a full rebuild is not cost or duration. It is losing the undocumented business rules the existing system encodes. Years of accumulated edge-case handling is why the old code looks messy, and it is also why it works. Rebuilds fail when the new system is cleaner and does not handle the fourteen exceptions the old one had learned about.

Recovering the rules before you replace them

Whichever path you choose, the domain knowledge in the existing system has to be extracted, and it is rarely written down.

Four sources. The code itself, read specifically for conditionals and special cases rather than for structure, since each one usually encodes a real situation somebody encountered. The people who use it, who know which fields matter and which are ignored. Support tickets and change history, which document the problems that shaped it. And the data, where unexpected values and patterns reveal behaviour nobody documented.

Budget real time for this. It is not analysis paralysis, it is the difference between a replacement that works and one that reopens fourteen resolved problems.

Data migration, the line nobody budgets

Migration is its own project and routinely 10 to 20 percent of a replacement build, and it is absent from almost every initial estimate.

What it involves: mapping old schema to new, which is where you discover fields used for two purposes and dates stored in three formats. Cleaning, because legacy data contains duplicates, orphans, and values that violate their own rules. Validation, comparing record counts and totals before and after. A rehearsal on production-scale data before the real run. And a rollback plan.

Then a parallel-running period where both systems operate and outputs are reconciled. Cutting over on day one with no reconciliation is how a data problem becomes a month of untangling, and in financial or regulated contexts it is how it becomes an audit finding.

‍


Frosted migration arrow of tiles with red seam

‍

Cost and timeline

An audit is $5,000 to $25,000 over one to three weeks. Targeted refactoring of specific problem areas is 20 to 50 percent of a rebuild cost. Incremental replacement of a mid-sized business system typically runs $120,000 to $350,000 across 9 to 24 months, delivered in pieces. A full rebuild of a comparable system is $100,000 to $300,000 over 6 to 14 months, plus migration and parallel running.

Bolder Apps builds backends in Laravel, Yii2, and Node.js, front ends in React with Ant Design or Material, and mobile in Flutter, FlutterFlow, Swift, and Kotlin, prices project work fixed-scope rather than hourly, and sells discovery and audits as standalone engagements. On modernisation work the scope items worth naming explicitly in any proposal are data migration, the parallel-running period, and rule recovery, because all three are real work and all three are commonly omitted from the estimate that wins the bid.

Sequencing a modernisation programme

Modernisation delivered as one large project is the highest-risk version. Sequenced, each step is independently justifiable.

First, stabilise. Add monitoring so you know what is actually failing, get deployment to a repeatable state, and verify that backups restore. None of this is modernisation and all of it makes everything after it safer.

Second, add tests around the areas you intend to change, which is what makes the changes safe rather than hopeful. Comprehensive coverage is not the goal; coverage of the paths you are about to touch is.

Third, create a seam if none exists. An API boundary or service boundary you can substitute behind, which is the precondition for incremental replacement.

Fourth, replace the highest-pain area behind that seam, then the next. Each step ships and each step is independently valuable.

Fifth, stop when the remaining old system is good enough. This step is the one nobody plans and the one that saves the most money, because full replacement is rarely necessary once the painful parts are gone.

Managing the business through it

Three practices that keep a modernisation from consuming the organisation.

Keep a feature capacity reserve. A modernisation programme that freezes all product work for a year creates commercial pressure that eventually forces a shortcut. Reserve twenty to thirty percent for the roadmap even during heavy replacement work.

Report progress in business terms rather than technical ones. A stakeholder cannot evaluate services migrated. They can evaluate that the reporting that took three days now takes an hour.

Decide in advance what you will not modernise. Explicit exclusions prevent the programme expanding to fill available budget, which is the pattern that turns a two-quarter effort into a permanent one.

Bolder Apps prices project work fixed-scope rather than hourly and sells discovery and code audits as standalone engagements. On modernisation the value of a phased fixed-scope structure is that each phase has a boundary, which is what lets you decide between phases rather than committing to an outcome nobody can yet specify.

When to leave it alone

Three situations where the honest answer is not yet.

The system works, changes are rare, and the technology is still supported. Modernising software you barely touch is spending money to feel modern.

The business process it supports is about to change. Replacing a system and then discovering the process it encodes is being redesigned means doing the work twice.

You cannot fund it to completion. A half-modernised system, two architectures running in parallel with no plan to finish, is worse than either alternative and is the most common outcome of an underfunded modernisation.



Sources

  • OWASP Application Security Verification Standard, owasp.org
  • NIST Special Publication 800-53, security and privacy controls
  • Martin Fowler's writing on incremental replacement and refactoring patterns, martinfowler.com
  • Amazon Web Services and Microsoft Azure published migration documentation
  • PostgreSQL documentation on data migration and transaction isolation
Quick answers

Frequently Asked Questions.

How do we know if our system is genuinely legacy?

Ask how long a small, well-understood change takes from request to production, and how confident the team is that it will not break something else. If the answer is weeks and not confident, it is legacy regardless of age. If it is days and reasonably confident, it is not.

Should we modernise the interface or the backend first?

The backend, in most cases, because the interface is the visible part and the backend is usually the actual constraint. Interface-first modernisation produces a modern-looking product with the same inability to change, and it also frequently paints you into supporting a new interface against an old data model.

Can we modernise while continuing to add features?

Under incremental replacement, yes, and it is one of the approach's main advantages. Under a full rebuild you are effectively running two development efforts, which is why feature work usually freezes and why rebuilds are commercially risky.

How long should parallel running last?

Long enough to cover a full business cycle for whatever the system does, which for financial or reporting systems means at least one month-end close and ideally a quarter. Shortening it to save cost is the compression that produces the reconciliation problems.

What is the most common reason modernisation projects fail?

Underestimating the domain knowledge in the old system, followed by omitting data migration from the budget. Both are addressable during discovery, and both are cheaper to address there than in month eight.

Get in touch

Let's discuss your goals

Schedule a meeting via the form here and we’ll connect you directly with our director of product—no salespeople involved.

What happens next?

Book a discovery call
Discuss and strategize your goals
We prepare a proposal and review it collaboratively
Clutch Boutique client logo
Clutch Award Badge
Clutch Award Badge

Bolder Starts Here

Please enter a valid phone number
Join 30+ founders who shipped with Bolder Apps
By submitting this form, you agree to our Terms of Use and Privacy Policy
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.