Microsoft released .NET 11 yesterday. On the same day, .NET 8 and .NET 9 reached end of support. If you have a bespoke web app, API or internal tool built in the last three years on Microsoft's stack, there's a decent chance it runs on one of those two, and as of today it won't get any more security fixes.
Microsoft's own announcement doesn't dress it up: "Move to a supported release to continue receiving fixes." Fair enough. Here's what that means in practice and how to decide where to go.
What actually changed
According to Microsoft's .NET support policy, the last patches were .NET 8.0.34 and 9.0.23, both released on 10 November 2026. That's it. Nothing more is coming for either version.
Your app won't stop working this morning. Nothing switches off. The risk is slower and quieter than that. The next time a security flaw turns up in the runtime or in ASP.NET Core, the fix will go into .NET 10 and .NET 11 and not into the version you're running. I wrote about the .NET Brotli flaw a couple of weeks ago, which was patched across .NET 8, 9 and 10. Next time, 8 and 9 won't be on the list.
If you have to answer security questionnaires, or you hold Cyber Essentials, unsupported software is also something you're expected to deal with, not something you can just leave running.
.NET 10 or .NET 11?
This is the bit that catches people out, so it's worth being clear. Microsoft alternates between two kinds of release:
- LTS (Long Term Support): even-numbered versions, supported for three years. .NET 10 is LTS.
- STS (Standard Term Support): odd-numbered versions, now supported for two years. .NET 11 is STS.
.NET 10 came out in November 2025 and .NET 11 came out yesterday, but both reach end of support on the same day: 14 November 2028. So for anyone moving off .NET 8 or 9 today, picking the LTS release doesn't buy you any extra time. You get two years either way.
Microsoft's advice is to choose .NET 11 for the latest capabilities, or .NET 10 if its LTS lifecycle suits you better. My take, for a typical business app, is that the decision comes down to your dependencies rather than the dates.
.NET 10 has been out for a year, so the libraries and packages your app relies on have had time to catch up with it. .NET 11 brings C# 15 with union types, more runtime performance work, OpenAPI 3.2 as the default in ASP.NET Core, and a better EF Core. But if one of your third-party packages doesn't support .NET 11 yet, you'll be stuck waiting. Also worth knowing: Microsoft says EF Core 11 requires .NET 11, so you can't pick up the new EF Core features while staying on 10.
If your app is quiet, stable and mostly needs to keep running safely, .NET 10 is the lower-risk move today. If you're actively developing it and want the new language features, .NET 11 is reasonable, as long as everything you depend on supports it.
How to check what you're running
You don't need to be a developer to get a straight answer to this, but you will need someone who can look at the code and the server. Ask them to check three places.
- The project files. Each .csproj file has a TargetFramework line. If it says net8.0 or net9.0, that project needs moving.
- The server. Running "dotnet --list-runtimes" shows which runtimes are installed. On Windows with IIS, the ASP.NET Core Hosting Bundle needs updating too.
- The containers. If the app runs in Docker, look at the base image in the Dockerfile. Something like aspnet:8.0 means it's still on 8.
One thing Microsoft points out that's easy to miss: installing a new SDK doesn't retarget your app on its own. Someone has to change the target framework, update the packages, rebuild, test and deploy. It's not a big job for a well-kept app, but it isn't nothing either.
What the upgrade actually involves
For a tidy, well-tested app, moving from .NET 8 to 10 is usually straightforward. You change the target framework, update the Microsoft packages to match, work through the breaking changes list Microsoft publishes for each version, run the tests and deploy.
Where it gets harder is the stuff around the code. Third-party packages that have been abandoned. Code nobody has touched since the original developer left. No automated tests, so nobody's quite sure what "it still works" means. A deployment process that lives in one person's head. None of it is a reason to put the upgrade off. It's just the reason it's worth having a proper look before you start rather than halfway through.
If the app was written with a lot of help from AI tools, it's worth checking it carefully too. Generated code can pull in whatever package versions were current when it was written, and it doesn't always leave you with tests that will catch what an upgrade breaks.
Don't just do it once
The bigger lesson here is the calendar. Every .NET version now has a fixed end date, and Microsoft publishes it on release day. .NET 10 and 11 both run out in November 2028. Put that in the diary now, and plan to move again sometime in 2028 rather than finding out the week it happens.
The same goes for everything underneath the app: the operating system, the database server, the web server. I've written before about what happens when that gets missed, from servers left on CentOS 7 to old PHP apps that never got moved on. The pattern's the same every time. It works, so nobody touches it, until something goes wrong.
If you'd like a hand
If you're not sure what your app runs on or how big the upgrade is, our code audit (£250 + VAT) will tell you what you've got, what's out of date and what moving it involves, in plain English. If you'd rather not think about end-of-life dates again, Look after it (from £355 a month + VAT) keeps bespoke software patched and up to date. And if the person who built it has moved on, taking on existing code is something we're happy to do.
Either way, check that TargetFramework line this week. It takes two minutes.
Cheers, Rob

