.NET 8 and .NET 9 Both Die on November 10. Your Upgrade Is an Engineering Project, Not a Version Bump.

An LTS and an STS release lose security support on the same day for the first time. Changing one line in the project file is the easy part. What actually breaks on the way to .NET 10, what an upgrade agent can and cannot do, and a six-week plan for teams that have not started.

Engineering.NET 8 and .NET 9 Both Die on November 10. Your Upgrade Is an Engineering Project, Not a Version Bump.

Why Do Two .NET Versions Expire on the Same Day?

Every November for the last few years, a .NET version quietly fell out of support and most teams noticed only when a scanner turned red. This November is different, because two versions go at once. According to the official .NET support policy page, .NET 8, released on November 14, 2023 as a Long Term Support release, and .NET 9, released on November 12, 2024 as a Standard Term Support release, both reach end of support on November 10, 2026. The only supported production release after that date is .NET 10, an LTS release supported until November 14, 2028.

The coincidence is a side effect of a policy change. In 2025 Microsoft extended STS releases from 18 to 24 months of support, starting with .NET 9. The stated reason was dependency friction: out-of-band libraries such as Aspire and Microsoft.Extensions.AI sometimes pull in package versions from newer annual releases, which put companies with LTS-only policies in an awkward position. The longer STS window fixed that, and it also moved .NET 9's end date onto the same day as .NET 8's.

Microsoft stated the consequence plainly in its June 29, 2026 end-of-support announcement: applications built on .NET 8 or .NET 9 will continue to run, but no new security updates will be issued for either version and technical support ends. A future Visual Studio 2022 servicing update will mark both runtimes as out of support. The recommended path is .NET 10, and the upgrade instruction in the post is a single line: change the TargetFramework property to net10.0.

That instruction is accurate and misleading in equal measure. It is the right first step. It is almost never the last one, and the gap between the two is where teams lose weeks. The population affected is not small: in the 2025 Stack Overflow Developer Survey, 21.3% of professional developers said they had worked with ASP.NET Core, and C# sat at 29.9% among professionals. A large share of that code is running on 8 or 9 right now, because 8 was the LTS release most organisations standardised on.

One more date matters for planning. .NET 11 reached its first release candidate on September 8, 2026 and ships in November, but it is an STS release. If your organisation only runs LTS versions, .NET 10 is the target, and it will stay the target until November 2027.

Key Takeaways

  • .NET 8 (LTS) and .NET 9 (STS) both lose support on November 10, 2026
  • The shared date comes from STS support being extended from 18 to 24 months
  • Applications keep running after that date; security patches and technical support stop
  • .NET 10 is the LTS target, supported until November 14, 2028

"It Still Runs" Is the Wrong Test

The most common response to an end-of-support notice is a shrug, and it is based on a true observation: nothing turns off. The runtime does not check the calendar. The site will serve traffic on November 11 exactly as it did on November 9. The problem is not what happens that day. It is what happens the next time a serious vulnerability is found in the runtime or in ASP.NET Core.

The last twelve months provided a clean example. In October 2025, Microsoft patched CVE-2025-55315, an HTTP request smuggling flaw in the Kestrel web server, and its security response centre explained why it scored 9.9: the flaw was a security feature bypass that could affect how applications enforce authentication and authorisation. BleepingComputer reported it as the highest-severity ASP.NET Core flaw ever, with fixes shipped for ASP.NET Core 8.0 and 9.0 among others. For teams on those versions, remediation was installing an update and restarting. For a team on an out-of-support version, there would have been no update to install.

That is the real shape of the risk. After November 10, the next flaw of that class gets a fix for .NET 10 and nothing for 8 or 9. At that point you are no longer planning an upgrade; you are doing one under incident conditions, with a public exploit write-up already circulating and a team that has never touched the breaking-change list.

Managed hosting does not change this. The Azure App Service language runtime support policy says apps on an end-of-support runtime continue to run unchanged, but App Service cannot provide security patches or related customer support for that version. The platform keeps the lights on; it does not keep your runtime safe.

There is also a slower cost that shows up before any exploit does. Dependency scanners, container image scanners and customer security questionnaires all treat end-of-life runtimes as findings. Each one becomes a conversation, an exception request or a delayed deal. Individually these are small. Across a portfolio of services they become a steady drain on the same senior engineers who should be doing the upgrade.

The Compliance Clock Is Now Running Alongside the Support Clock

For companies selling software into the EU, end of support is no longer only a security hygiene issue. The Cyber Resilience Act's reporting obligations started in September 2026, and a breakdown of what that means for end-of-life dependencies sets out the timeline: starting September 11, 2026, manufacturers must report actively exploited vulnerabilities within 24 hours, followed by a detailed notification within 72 hours, with full product conformity requirements following on December 11, 2027.

An unpatched runtime makes that obligation uncomfortable in a very specific way. If an actively exploited flaw lands in ASP.NET Core and your product runs on .NET 8, you will be reporting a vulnerability you have no vendor fix for, and explaining what you are doing about it. We covered the wider mechanics in our piece on the CRA reporting deadline, and the supplier side in how NIS2 flows obligations down to software suppliers. The short version: regulated customers increasingly ask, in writing, whether you run supported components, and "yes, except the runtime" is not an answer procurement teams like.

None of this means the sky falls on November 11. It means an end-of-life runtime has moved from a technical debt item that engineering can defer to a line in a compliance register that someone outside engineering will ask about. That changes who cares, and it changes how quickly a deferral turns into an escalation.

What Actually Breaks on the Way to .NET 10

Microsoft maintains a breaking changes list for .NET 10, organised by area and labelled as binary incompatible, source incompatible or behavioural. The distinction matters more than the length of the list. Source-incompatible changes announce themselves: the build fails or warns, and someone fixes it. Behavioural changes compile cleanly and then do something different at runtime, which is where upgrades actually hurt.

In web applications, the ASP.NET Core 10 breaking changes include several that touch older codebases directly. WebHostBuilder, IWebHost and WebHost are now obsolete, which affects any service still bootstrapped the pre-minimal-hosting way. Razor runtime compilation is obsolete. The WithOpenApi extension method and the MVC API analyzers are deprecated. And one behavioural change deserves its own test: cookie authentication no longer redirects to a login page for requests to known API endpoints. If a front end or integration relied on that redirect, it now gets a status code instead, and nothing in the compiler will tell you.

Deployment is the next place surprises live. Default .NET 10 container tags now use Ubuntu instead of Debian, and Debian images are not shipped for .NET 10 at all. Most applications will not notice. The ones that install native packages in their Dockerfile, depend on specific system libraries, or have security tooling pinned to a Debian base will. On the SDK side, dotnet restore now audits transitive packages, which is good security practice and a common cause of a previously green pipeline failing when warnings are treated as errors.

The core libraries carry quieter behavioural changes: the default trace context propagator moves to the W3C standard, which can change how distributed traces stitch together across services still on older versions; BackgroundService now runs all of ExecuteAsync as a task; configuration preserves null values; System.Text.Json checks for property name conflicts. Each one is minor on its own. In a system with a dozen services, a message bus and a tracing backend, several of them will intersect.

Key Takeaways

  • Source-incompatible changes fail the build; behavioural changes compile and then behave differently
  • WebHostBuilder, Razor runtime compilation and WithOpenApi are obsolete or deprecated in ASP.NET Core 10
  • Cookie auth no longer redirects to a login page for known API endpoints, a change only tests will catch
  • Default container images move from Debian to Ubuntu, and restore now audits transitive packages

The TargetFramework Line Is the Smallest Part of the Work

In the upgrades we run, the version change itself is the fastest part. The time goes into four places, and a realistic plan budgets for each of them before anyone opens a branch.

The first is third-party dependencies. Every NuGet package needs a version that supports .NET 10, and the ones that matter are rarely the popular open-source libraries, which usually update quickly. They are the commercial UI component suites, the payment and ERP SDKs, the internal shared libraries nobody has owned since a reorganisation, and the one package pinned three major versions back because the last upgrade attempt broke something. An inventory of these, with a named owner and an upgrade path for each, is the single most useful document in the whole project.

The second is tests, or the lack of them. Behavioural changes are only caught by tests that exercise the behaviour. A service with solid integration tests around authentication, serialisation and background processing can be upgraded with confidence. A service without them needs a thin layer of characterisation tests written on the old version first, so there is something to compare against. This is unglamorous work, and skipping it is the most reliable way to turn a two-week upgrade into a two-month incident tail.

The third is the pipeline and the platform: SDK images in CI, container base images, Helm charts or App Service settings, and any scripts that pin a runtime version. The fourth is observability. If trace propagation or log output changes, dashboards and alerts built on the old shape can go quiet without anyone noticing. Checking that the signals you rely on still arrive after the upgrade belongs on the definition of done, not in the post-release retro.

Can an Upgrade Agent Do This for You?

Partly, and the part it does well is substantial. The GitHub Copilot upgrade agent documentation describes a three-stage workflow: an assessment that lists breaking changes, API compatibility problems and deprecated patterns; a plan that sets out the upgrade strategy, dependency paths and risk mitigations; and an execution stage that breaks the plan into sequential tasks with validation criteria. It works on a new branch, writes its state to Markdown files in the repository, and creates a Git commit for each portion of the work so changes can be reviewed or rolled back. Supported scenarios go beyond version bumps to include Newtonsoft.Json to System.Text.Json, SqlClient migration and moving Azure Functions to the isolated worker model.

That design is sensible, and it matches what we see across agentic tooling generally: the value comes from the plan and the audit trail as much as from the code changes. An agent is very good at the source-incompatible layer, where the compiler provides an unambiguous signal and the fix is well documented. It is fast at mechanical churn across dozens of projects, which is exactly the work that used to make large solution upgrades tedious enough to postpone.

The limits are the same ones that apply to any coding agent working on an unfamiliar system. The documentation itself says that when the agent cannot correct a problem, it asks for help. Behavioural changes that compile cleanly give it no signal unless the tests do. It cannot know that a partner integration depends on the old login redirect, that a native library in the Dockerfile is Debian-specific, or that the commercial grid component your back office depends on has no .NET 10 build yet. Those are facts about your system and your business, not about the framework.

The practical pattern that works: let the agent produce the assessment and do the mechanical work, and put an engineer who understands the system in charge of the plan, the tests and the review. We have written before about why the repository, not the agent, is usually the bottleneck. Upgrades are a sharp illustration: a codebase with tests and clear ownership gets most of the agent's benefit, and one without gets a large, confident diff that nobody can verify.

Key Takeaways

  • Upgrade agents now handle assessment, planning and mechanical code changes with a per-task commit trail
  • They are strongest on source-incompatible changes, where the compiler gives a clear signal
  • Behavioural changes, vendor packages and deployment specifics still need engineers who know the system
  • Tests determine how much of an agent's output you can actually trust

If You Cannot Make the Date: Paid Extended Support

Some systems will not be on .NET 10 by November 10. Large solutions, regulated change processes and frozen vendor dependencies all make that realistic, and the honest answer is that a documented bridge beats an undocumented risk.

Commercial extended support now exists for this. HeroDevs announced Never-Ending Support for .NET 8 in April 2026, positioned as a drop-in replacement runtime that continues security patches and CVE remediation after Microsoft's support ends, and the same announcement acknowledges that large migrations can span multiple quarters. The offering we found covers .NET 8; if you are on .NET 9, confirm availability rather than assuming it.

Treat this as a bridge with a fixed end, not a destination. It buys time for the migration, keeps the compliance register honest, and gives you something to write in the customer questionnaire. It does not reduce the upgrade work, and every month on it is a month of licence cost for a runtime you intend to leave. The right way to buy it is alongside a dated migration plan, so the bridge has a scheduled demolition.

A Six-Week Plan for Teams That Have Not Started

As of this writing, November 10 is a little over six weeks away. For a single application or a modest service portfolio, that is enough time if the work is sequenced properly. For a large estate, it is enough time to upgrade what matters most and put a documented bridge under the rest.

Weeks one and two are inventory and triage. List every deployable on .NET 8 or 9, rank them by exposure (internet-facing, handles authentication, processes payments or personal data) and by difficulty (dependency count, test coverage, vendor packages). Run an agent assessment on each and read it critically. Decide now which systems will migrate before the deadline and which get extended support. Weeks three and four are execution on the high-exposure systems: branch, upgrade, fix the build, then spend most of the time on tests around authentication, serialisation, background jobs and tracing. Weeks five and six are staging soak, container and pipeline changes, and production rollout with a rollback plan.

The constraint in almost every case is not knowledge of .NET 10. It is senior engineering time that is already committed to the roadmap. That is precisely the situation a dedicated nearshore team is suited to: a bounded, well-specified piece of work that needs experienced engineers for a defined period, without pausing product delivery. At Stepto, our .NET engineers in Serbia run framework upgrades as a fixed-scope engagement: an inventory and risk assessment in the first week, agent-assisted migration with human review, characterisation tests where coverage is thin, and a handover that leaves your team owning a supported, documented system. Working in CET means a full working-day overlap with European teams and a solid morning overlap with the US East Coast, which matters when production cutovers need both sides in the room.

If you are carrying more than one generation of debt, for example services still on .NET Framework alongside the .NET 8 estate, this is also a sensible moment to plan the longer path. Our application modernisation work typically starts with the deadline-driven upgrade and uses the resulting inventory to sequence the rest.

Key Takeaways

  • Weeks 1-2: inventory every .NET 8 and 9 deployable, rank by exposure and difficulty, decide migrate vs. bridge
  • Weeks 3-4: upgrade high-exposure systems first, spending most of the time on behavioural tests
  • Weeks 5-6: staging soak, pipeline and container changes, production rollout with a rollback plan
  • The usual bottleneck is senior engineering time, not framework knowledge

Start With an Inventory, Not a Branch

November 10 will not break anything on the day, which is exactly why it is easy to miss. What changes is that the next serious ASP.NET Core or runtime vulnerability gets fixed for .NET 10 only, while EU reporting rules and customer security reviews make an unpatched runtime harder to explain than it used to be. The upgrade itself is well-trodden: the breaking changes are documented, upgrade agents handle much of the mechanical work, and most applications need weeks, not quarters. The teams that struggle are the ones that treat it as a version bump, discover the behavioural changes in production and find their senior engineers already committed elsewhere. Start with an inventory, put tests around the behaviour that matters, let tooling do the churn and let experienced engineers own the plan. If your team does not have the capacity to do that before November, a bounded engagement with experienced nearshore .NET developers is considerably cheaper than an upgrade done under incident conditions.

Building a team in Eastern Europe?

StepTo helps European and US companies build senior-led nearshore engineering teams in Serbia. Let's talk about what your next engagement could look like.

Start a conversation
I

Written by

Igor Gazivoda

Founder & CEO · StepTo

Igor has 15+ years in software engineering and business development. He specializes in scaling engineering teams, nearshore strategy, and AI-driven product development. He holds a Master's in Computer Science from the University of Belgrade.

LinkedIn →
Performance-led engineering

Want senior engineers who move work forward, not just tickets?

Work with accountable, English-fluent professionals who communicate clearly, protect quality, and deliver with a steady operating rhythm. Cost efficiency matters, but performance is why clients stay with us.

Delivery signals · senior engineering team
Senior ownership
Lead-level
Delivery rhythm
Weekly
Timezone overlap
CET
1 teamaccountable for outcomes, communication, and execution