Moving a business-critical application from .NET Framework or older ASP.NET to modern .NET is not simply a framework upgrade. The difficult part is protecting years of business behaviour while improving the architecture, delivery model and supportability of the platform.
.NET 10 is the current long-term support target, but the safest destination depends on your estate, dependencies and release constraints. This guide focuses on the decisions that remain useful beyond any single runtime version: assessment, boundaries, testing, sequencing and controlled cutover.
Start with the business constraint, not the runtime
Before choosing a target architecture, identify what the existing platform is preventing the organisation from doing. Slow releases, unsupported dependencies, fragile integrations, limited observability and knowledge concentrated in a few people are stronger reasons to modernise than age alone.
If the decision is still framed as rewrite versus retain, use the rewrite-or-modernise decision framework before committing to a programme.
1. Assess the existing estate
- Inventory applications, runtimes, libraries and unsupported third-party dependencies.
- Map databases, scheduled processes, file exchanges, APIs and external integrations.
- Identify business-critical journeys and the code paths that implement them.
- Measure current deployment frequency, failure rate, support effort and recovery time.
- Record where knowledge or operational ownership is concentrated.
The Legacy .NET Modernisation Checklist provides a structured 32-question starting point for this assessment.
2. Choose a supported target deliberately
For new migration work in 2026, .NET 10 is the natural LTS target in many estates. That does not mean every component must move directly to it in one step. Some applications benefit from dependency upgrades, project-format changes or boundary extraction before the runtime move itself.
Avoid coupling the business case to a particular version number. The outcome should be a platform that is easier to change and keep supported through future .NET releases.
3. Protect behaviour before changing it
Legacy applications frequently contain undocumented behaviour. Build evidence before refactoring: characterisation tests, integration tests, representative production data, telemetry and side-by-side output comparisons can all reduce uncertainty.
AI-assisted analysis can accelerate code comprehension and test scaffolding, but generated explanations and tests still need validation against real business behaviour. The AI-assisted modernisation playbook covers this in more detail.
4. Find the smallest useful boundary
A whole-platform migration creates a very large blast radius. Look instead for capabilities with understandable inputs and outputs: payments, calculations, document generation, customer servicing or a specific integration are typical examples.
Introduce a stable API or service boundary where it creates real independence. Do not create microservices simply because the target runtime is modern; modular code with clear ownership is often a better first step.
5. Modernise the delivery system too
- Automate builds and repeatable deployments.
- Move environment-specific configuration out of application binaries.
- Add useful logging, metrics and tracing before increasing architectural distribution.
- Create rollback or feature-control mechanisms for risky migrations.
- Keep security and dependency patching part of the normal engineering process.
A runtime upgrade without these improvements can leave the organisation with newer code but the same delivery problems.
6. Run old and new paths together where possible
Parallel running, shadow processing and incremental traffic movement are valuable because they let the new implementation prove itself against known production behaviour. This is especially useful for calculations, integrations and workflows where incorrect output may be more dangerous than a visible technical failure.
7. Measure whether modernisation is actually working
- Lead time for a normal change
- Deployment frequency and rollback confidence
- Production incident and support effort
- Time required to diagnose failures
- Dependency and runtime support status
- How independently a capability can now be changed
Common migration mistakes
Treating migration as a code conversion. Syntax is usually easier than behaviour, dependencies and operational change.
Reproducing every historical exception. Modernisation is an opportunity to decide which behaviours the business genuinely still needs.
Introducing distributed architecture too early. A poorly understood monolith split into services becomes a poorly understood distributed system.
Leaving testing until after the migration. Tests are most valuable before behaviour starts moving.
Planning one final cutover. If the programme delivers no useful value until everything is complete, much of the risk of a big-bang rewrite remains.
A safer definition of done
The goal is not simply “running on .NET 10”. A successful modernisation leaves the organisation with supported technology, clearer boundaries, protected business behaviour, repeatable delivery, useful observability and a team that can continue evolving the platform without another transformation programme.
Need to decide where to start?
I help CTOs and engineering leaders assess legacy .NET estates and turn the findings into a staged modernisation roadmap.
