.NET 11 Ships: C# 15 Union Types, Runtime Async .NET 11 shipped on November 10, the same day .NET 8 and .NET 9 both reached end-of-support, leaving teams on either version without security patches. The release brings C# 15 union types, which do not round-trip through System.Text.Json at launch and require a custom converter across network boundaries, plus runtime async moved into the JIT with no code changes required and on by default for projects targeting net11.0. Microsoft recommends .NET 10 LTS, supported through November 2028, for organizations needing a longer runway than .NET 11's 24 months of STS support, and .NET 11 also raises minimum CPU requirements so the runtime will not start on older hardware. .NET 8 and .NET 9 both hit end-of-support on November 10 — the same day .NET 11 shipped. If your team is running either version, you are now on unsupported software with no security patches in the pipeline. That double expiration is easy to miss, and Microsoft did not exactly advertise it loudly. The good news is that .NET 11 is a genuinely strong release: C 15 ships with union types the most-requested C feature in years , async/await moves into the JIT with zero code changes required, and the SDK now includes a first-class AI agent stack. Here is what changed and what you need to decide before the week is out. First, the Version Math The expiration stacking here is unusual. .NET 8 was LTS with a three-year window from November 2023 — that runs out November 2026. .NET 9 was STS with two years from November 2024 — same end date. They both expired yesterday. .NET 11 is also STS, giving you 24 months of support. If your organization needs a longer runway, Microsoft’s EOL post https://devblogs.microsoft.com/dotnet/dotnet-8-9-end-of-support/ recommends .NET 10 LTS, which is supported through November 2028. The upgrade path from .NET 8 to .NET 10 is a project file edit plus a read through both the .NET 9 and .NET 10 breaking-change lists. For most applications it is a few days, not a rewrite. C 15: Union Types Land Union types have been the top community request for C for the better part of a decade. They are here now. The new contextual union keyword does not break existing code that uses “union” as an identifier. You declare a type that is exactly one of a closed set of cases, and the compiler knows all of them: public union Pet Cat, Dog, Bird ; // Implicit conversions from each case type Pet pet = new Dog "Rex" ; // Exhaustive switch — no discard arm needed var label = pet switch { Cat c = $"Cat: {c.Name}", Dog d = $"Dog: {d.Name}", Bird b = $"Bird: {b.Name}" }; Generic unions make result modeling clean without a library dependency: public union Result