Millions of business-critical apps still run on .NET Framework 4.x. Microsoft continues to support 4.8, but make no mistake — it's frozen. No new features, no performance gains, no cross-platform, no modern cloud tooling. Every year you stay put, the gap between your app and the ecosystem widens, and the eventual move gets more expensive. This post is an honest look at what migrating to modern .NET really costs, how long it takes, and how to do it without betting the business on a rewrite.
Why This Isn't 'Someday' Anymore
The pressure to move is rarely about the framework itself — it's about the business consequences of standing still. Hiring gets harder: strong .NET developers don't want to work on a frozen 2015-era stack, and the ones who will cost you in other ways. Performance costs money: modern .NET is often 2–4x faster for the same workload, which translates directly into smaller cloud bills. You're locked to Windows-only hosting and shut out of Linux containers, Kubernetes, and cheaper deployment options. And your security horizon is shrinking — every dependency you can't upgrade is a risk that compounds.
What Actually Has to Change — and What Doesn't
Here's the reassuring part: a migration is not a rewrite. The core of your application — your C# business logic, domain models, calculations, and most service classes — moves across with little or no change. The work concentrates in a predictable set of areas, and knowing which is which upfront is what separates a 3-week job from a 3-month one.
The Green Path — Moves Easily
Plain C# class libraries, domain and business logic, most LINQ, and the majority of well-maintained NuGet packages (which now target .NET Standard or .NET) come over cleanly. Entity Framework 6 has a supported path to EF Core — it needs care around query translation and lazy loading, but it's a known quantity, not a landmine.
The Red Path — Needs Real Rework
A few technologies have no lift-and-shift path and drive most of the cost. ASP.NET Web Forms has no equivalent in modern .NET — it becomes a UI rewrite in Blazor or ASP.NET Core MVC. WCF services move to CoreWCF, gRPC, or REST. Anything touching System.Web, AppDomains, .NET Remoting, or Windows-only APIs needs redesign. And any third-party library without a .NET Standard/Core version has to be replaced. The single biggest cost predictor in any quote is how much of your app sits on this red path.
Configuration is a smaller but universal change — static web.config and ConfigurationManager lookups give way to appsettings.json and injected configuration:
// .NET Framework — static config lookups scattered everywhere
var conn = ConfigurationManager.ConnectionStrings["Db"].ConnectionString;
var apiKey = ConfigurationManager.AppSettings["ApiKey"];
// Modern .NET — appsettings.json + injected IConfiguration
public class PaymentService(IConfiguration config)
{
private readonly string _apiKey = config["Payments:ApiKey"]!;
// Better still: strongly-typed IOptions<PaymentOptions>
}The Strategy: Strangle It, Don't Rewrite It
The riskiest thing you can do is stop feature work, spend six months rebuilding everything in parallel, and attempt a single cutover. Smart migrations are incremental — you migrate one module at a time, ship each piece to production, and keep the business running throughout. This is the 'strangler fig' pattern, and it's how I approach every migration I take on.
Step 1 — Assess Before You Touch Anything
Run Microsoft's free .NET Upgrade Assistant and Portability Analyzer to inventory every dependency and flag red-path components automatically. This assessment is a few days of work and it's the most valuable thing you can do — it turns a vague, scary project into a costed, ordered backlog.
Step 2 — Multi-Target Shared Libraries
Retarget your shared class libraries to .NET Standard so both the old Framework app and the new modern app can consume the exact same code during the transition. No duplication, no fork to keep in sync.
Step 3 — Put a Reverse Proxy in Front
Using YARP, the new modern app becomes the front door. Routes you've already migrated are served by modern .NET; everything else is transparently proxied to the untouched legacy app. Users never see the seam, and you can migrate — and roll back — one slice at a time.
// Program.cs — modern app is the front door.
// Migrated routes are served locally; everything else
// is proxied to the still-running .NET Framework app.
builder.Services
.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
// appsettings.json (YARP):
// "Routes": {
// "newBilling": { "ClusterId": "modern", "Match": { "Path": "/billing/{**rest}" } },
// "legacy": { "ClusterId": "framework", "Match": { "Path": "/{**rest}" } }
// }Step 4 — Migrate Module by Module, Ship Continuously
Start with the greenest, lowest-risk module to prove the pipeline, then work through the backlog by business value. Each module ships to production behind the proxy, so value lands every sprint instead of all at the end — and the project can pause or reprioritise at any point without leaving you stranded half-rewritten.
Realistic Timeline and Cost
Every app is different, but based on real projects, here are honest ballparks for a solo senior contractor. A library, API, or console/service migration that's mostly green-path: roughly $4,000–$9,000 over 2–4 weeks. A mid-size line-of-business app (WinForms/WPF or MVC on Framework, 10–20 screens, a few integrations): $15,000–$40,000 over 2–4 months, delivered in phases. A large Web Forms enterprise system that needs a genuine UI rebuild: $50,000+ and best treated as a staged programme, not a single project.
The honest caveat: Web Forms apps are the expensive case. There's no shortcut for the UI layer — it's a rewrite in Blazor or MVC — so if that's your situation, be sceptical of any quote that doesn't say so plainly.
Red Flags in a Migration Quote
Whoever you hire, watch for these. 'We'll just rewrite the whole thing' — the most expensive, highest-risk option, rarely the right one. No assessment phase — anyone quoting a firm number before running the Upgrade Assistant is guessing. A single big-bang cutover with no incremental delivery — that's how migrations blow their budget and their deadline. And no mention of the red path (Web Forms, WCF, System.Web) — it means they haven't actually looked at your app.
The best migrations aren't rewrites — they're careful extractions. Keep what works, modernise what doesn't, and ship every step to production.— Kathan N. Patel
If you're running a .NET Framework app and weighing the move, start with a number: the free Project Cost Estimator gives you an instant range with a phase-by-phase breakdown — no sign-up. When you're ready to scope it properly, book a free 30-minute call or see how I work. Migrating something AI-heavy or want to add AI while you modernise? That's covered on the AI integration page.