What a Legacy .NET Migration Actually Involves — For Non-Technical Stakeholders

May 19, 2026

When a team says an application has to move from .NET Framework to .NET 8, most stakeholders hear "upgrade."

An upgrade is what happens when your phone moves to a new operating system version. The thing keeps working, some details change, you carry on. That expectation is what makes the estimate look absurd when it arrives.

The more accurate description is that you're replacing the plumbing and wiring in an occupied building. It stays where it is and looks the same afterward. Everything behind the walls is different, nothing can be disconnected for long, and you won't know what's back there until you open them.

Where the time goes

Four categories, in roughly ascending order of unpredictability.

Dependencies. The application uses third-party components — a PDF library, a reporting engine, a charting control, an authentication package. Each needs a version compatible with modern .NET. Most have one. Some don't, because the vendor stopped supporting the product or went out of business, and that component has to be replaced. Replacing a reporting engine isn't a migration task; it's a project with its own testing and user-visible changes, and it's often the largest single item in the estimate.

Windows-specific functionality. .NET Framework is tied to Windows and older applications used that freely — the registry, COM components, Windows-only cryptography, server-side Office automation. Modern .NET is cross-platform, so this gets rewritten against different mechanisms. The volume is knowable in advance, making it the most predictable part of the work.

Configuration and infrastructure. Configuration, deployment, authentication and logging all changed between the platforms. Mechanical and rarely difficult, but it's where the schedule collides with other departments, because it needs people who don't report to the project.

Verification. Almost always the largest category, and the one cut first.

Modernizing the platform is half the job; proving the application still behaves identically is the other half. With automated tests you have a mechanism. Most applications this age have few or none, so before anyone can confirm the migration worked, someone has to establish what "worked" means — which reports produce which numbers, which workflows produce which outcomes — and then check them.

That's why the estimate looks disproportionate. A large share of it isn't moving the application. It's building the ability to tell whether the move succeeded.

What drives two months versus eight

Three variables, all knowable before committing to a number.

How many third-party dependencies have no supported successor. One replaced component can double a small migration.

How much Windows-specific code exists. A team can count this in a few days.

Whether meaningful test coverage exists. This is the largest single factor — the same application with tests and without differs by a factor of two or three, because verification has to be built from nothing.

Any estimate produced without examining those three is a guess. Asking for a short paid assessment first is reasonable: a week or two of inspection converts the range into something defensible, and it's the cheapest risk reduction available.

Where scope creep comes from

This project type has a specific trap. Once developers are inside a codebase that's been untouched for a decade, they will find things that are genuinely bad — poor structure, obvious inefficiencies, features built awkwardly. The instinct to fix them while in there is sincere and often technically correct.

It is also how a four-month migration becomes a nine-month rewrite. Every improvement adds behavior change, and behavior change adds verification, and verification is already the biggest category.

The rule worth enforcing: the migration changes the platform, not the behavior. If the application computed something wrong before, it computes it wrong afterward. Everything found along the way goes on a list, and the list becomes the next project, funded separately, on a supported platform where the work is far cheaper anyway.

This is unsatisfying to engineers and it is the discipline that gets migrations finished.

What finished looks like

A migration that technically compiles is not finished. That state is common and it's how projects stall at ninety percent: the application builds on the new platform, runs on a developer's machine, and cannot be deployed because the deployment process, the identity configuration and the verification were the remaining half.

Finished means the application is running in production on a supported platform, your team can deploy it without the migration engineer present, the numbers it produces have been checked against the numbers the old system produced, and the improvements found along the way are written down as a funded next step rather than half-implemented.

The last one matters more than it sounds. The value of a migration isn't the runtime version. It's that the system is now on a platform where the next piece of work is affordable.


Working through a problem like this?

Describe the system and where it's stuck. I'll tell you what the work actually involves.

Get in touch