.NET 11 reached general availability today, November 10, 2026: runtime 11.0.0 and SDK 11.0.100 are marked released in the dotnet/core metadata, following RC2 on October 13 and an RC3 with security fixes on October 25, and Visual Studio 18.12 bundles both. The timing matches the first day of .NET Conf 2026, November 10 to 13. It brings C# 15 union types, in-box Zstandard, and runtime async as an opt-in preview for your own code. It is a Standard Term Support release, and its end-of-support date is the detail most teams will plan around: November 14, 2028, the same day .NET 10 LTS expires. The devblogs "Announcing .NET 11" post had not yet appeared when this was written, so the What's new overview and the docs repositories are the record here.
C# 15: unions arrive and hierarchies close
C# 15 is the default language version for net11.0, and its headline is union types: public union Pet(Cat, Dog); declares a type that holds exactly one of its cases, converts implicitly from each, and gets exhaustiveness checking in switch. The closed modifier does the same for class hierarchies. A closed class is implicitly abstract, and a switch that handles every direct descendant needs no discard arm. The docs are candid about the catch: closure is not transitive, so intermediate classes must be marked closed too. Microsoft said at RC1 that C# 15 stabilizes unions, and neither feature needs LangVersion preview.
The block below shows both, plus collection expression arguments, where with(...) as the first element passes arguments to the collection's constructor.
1// Domain.cs (C# 15, the default for net11.0) 2public record class Cat(string Name); 3public record class Dog(string Name); 4public union Pet(Cat, Dog); 5 6public closed record class GateState; 7public record class Closed : GateState; 8public record class Open(float Percent) : GateState; 9 10public static class Domain 11{ 12 public static string Describe(Pet pet) => pet switch 13 { 14 Cat c => $"cat {c.Name}", 15 Dog d => $"dog {d.Name}", // exhaustive, no discard arm 16 }; 17 18 public static string Describe(GateState state) => state switch 19 { 20 Closed => "closed", 21 Open(var percent) => $"{percent}% open", 22 }; 23 24 public static HashSet<string> Tags(string[] values) => 25 [with(StringComparer.OrdinalIgnoreCase), .. values]; 26}
Smaller additions: extension indexers, so numbers[2] can work on an IEnumerable<int>, and labeled break and continue for nested loops. A reworked memory-safety model, in which unsafe on a member obliges its callers, sits behind LangVersion preview and a feature flag. Read it; do not ship it.
Runtime async and Zstandard: the plumbing
Runtime async replaces compiler-generated state machines with suspension and resumption handled by the runtime. In .NET 11 the runtime libraries are compiled with it, so the BCL's async code already runs on it in every .NET 11 app. For your own assemblies it remains a preview opt-in, though net11.0 projects no longer need EnablePreviewFeatures. Microsoft's sample shows a live stack trace shrinking from 13 frames to 5, and continuations now skip ExecutionContext capture when there is no AsyncLocal<T> state to restore. The DOTNET_RuntimeAsync environment variable is gone; the per-project opt-out is <UseRuntimeAsync>false</UseRuntimeAsync>.
1<!-- Api.csproj --> 2<Project Sdk="Microsoft.NET.Sdk.Web"> 3 <PropertyGroup> 4 <TargetFramework>net11.0</TargetFramework> 5 <Nullable>enable</Nullable> 6 <ImplicitUsings>enable</ImplicitUsings> 7 <!-- Preview: compile this project's async methods as runtime async --> 8 <Features>runtime-async=on</Features> 9 </PropertyGroup> 10</Project>
Zstandard is the library change backend engineers will touch first. ZstandardStream and ZstandardEncoder now live in System.IO.Compression beside GZipStream and BrotliStream, with the encoder and decoder shape Brotli has had for years. The reference assembly confirms the overloads used here: a CompressionLevel constructor, GetMaxCompressedLength, and span-based TryCompress, plus a ZstandardDictionary type for small, repetitive payloads.
1// Archive.cs (.NET 11) 2using System.IO.Compression; 3 4public static class Archive 5{ 6 public static async Task CompressFileAsync(string source, string target) 7 { 8 await using FileStream input = File.OpenRead(source); 9 await using FileStream output = File.Create(target); 10 await using var zstd = new ZstandardStream(output, CompressionLevel.SmallestSize); 11 await input.CopyToAsync(zstd); 12 } 13 14 // One-shot and span-based, no Stream involved 15 public static byte[] Compress(ReadOnlySpan<byte> payload) 16 { 17 var buffer = new byte[ZstandardEncoder.GetMaxCompressedLength(payload.Length)]; 18 return ZstandardEncoder.TryCompress(payload, buffer, out int written) 19 ? buffer[..written] 20 : throw new InvalidOperationException("Destination buffer too small."); 21 } 22}
The same release adds ZstandardCompressedContent for compressed HTTP request bodies, union support in System.Text.Json, LeftJoin, RightJoin and FullJoin in LINQ, IEEE 754 Decimal32, Decimal64 and Decimal128, and a run of process APIs such as Process.Signal(PosixSignal). The JIT gets its usual harvest, including a single-instruction Math.BigMul on x64.
ASP.NET Core 11 and EF Core 11 for backend work
ASP.NET Core 11 serializes C# unions anywhere System.Text.Json is used and describes them in OpenAPI as anyOf with no $type discriminator; they do not bind from route, query, header or form values. Zstandard joins the response-compression and request-decompression middleware and is enabled by default. Hosting now writes OpenTelemetry HTTP semantic-convention attributes onto the request activity, so OpenTelemetry.Instrumentation.AspNetCore is no longer needed; subscribe to the Microsoft.AspNetCore source.
EF Core 11 translates the new FullJoin to SQL FULL JOIN, adds MaxByAsync and MinByAsync, and exposes SQL Server's VECTOR_SEARCH() through VectorSearch(), experimental on both sides. dotnet ef database update --add scaffolds, compiles and applies a migration in one step, which suits containers that cannot rebuild. EF11 requires the .NET 11 runtime.
1// Program.cs (ASP.NET Core 11 + EF Core 11) 2// Packages: OpenTelemetry.Extensions.Hosting, OpenTelemetry.Exporter.Console 3// ShopContext (Customers, Orders, Blogs) is your EF Core model, registered elsewhere 4using System.IO.Compression; 5using Microsoft.AspNetCore.ResponseCompression; 6using Microsoft.EntityFrameworkCore; 7 8var builder = WebApplication.CreateBuilder(args); 9builder.Services.AddResponseCompression(); // zstd provider is on by default 10builder.Services.Configure<ZstandardCompressionProviderOptions>(o => 11 o.CompressionOptions = new ZstandardCompressionOptions { Quality = 6 }); 12builder.Services.AddOpenTelemetry().WithTracing(t => t 13 .AddSource("Microsoft.AspNetCore") 14 .AddConsoleExporter()); 15 16var app = builder.Build(); 17app.UseResponseCompression(); 18 19app.MapGet("/value", () => new IntOrString(42)); // union, serialized by System.Text.Json 20 21app.MapGet("/report", async (ShopContext db) => await db.Customers 22 .FullJoin(db.Orders, c => c.Id, o => o.CustomerId, 23 (c, o) => new { Customer = c, Order = o }) // FULL JOIN 24 .ToListAsync()); 25 26app.MapGet("/top-blog", async (ShopContext db) => 27 await db.Blogs.MaxByAsync(b => b.Posts.Count())); 28 29app.Run(); 30 31public union IntOrString(int, string);
What breaks on the way up
The compiler list is short and mostly about new keywords. Roslyn's breaking-change log records that union and closed are now contextual keywords in type declarations, so a type with either name needs an @ escape; with(...) inside a collection expression binds as constructor arguments; and nameof(this.P) in an attribute, accidentally legal since C# 12, is now an error. Span-typed collection expressions also got a narrower safe-context, which can surface new ref-safety errors in loops. Some of these already reached Visual Studio 18.3 and the 10.0.200 SDK.
1// Legacy.cs: C# 14 to C# 15 2-class union { } 3-class closed { } 4+class @union { } 5+class @closed { } 6 7 class C 8 { 9- union OldField; // C# 15: parsed as a union declaration (CS9370) 10- closed Other; // C# 15: incomplete declaration (CS1519) 11+ @union OldField; 12+ @closed Other; 13 string P = ""; 14 15- object[] Items(object x, object y, object z) => [with(x, y), z]; // error 16+ object[] Items(object x, object y, object z) => [@with(x, y), z]; 17 object with(object a, object b) => a; 18 19- [System.Obsolete(nameof(this.P))] void M() { } // now disallowed 20+ [System.Obsolete(nameof(P))] void M() { } 21 }
ASP.NET Core's breaking-change list runs to 22 entries. The ones most likely to fail a build or a contract test: the ConcurrencyLimiter middleware is gone with no 11.x package to restore, so move to the rate limiter; OpenAPI output defaults to 3.2, so pin 3.1 if a client generator chokes; Microsoft.OpenApi moves to 3.x; MVC compatibility options are removed; Kestrel tightens HTTP protocol compliance; and response compression always emits Vary: Accept-Encoding.
1// Program.cs: ASP.NET Core 10 to 11 2-using Microsoft.AspNetCore.ConcurrencyLimiter; 3-builder.Services.AddQueuePolicy(options => 4-{ 5- options.MaxConcurrentRequests = 2; 6- options.RequestQueueLimit = 25; 7-}); 8+using System.Threading.RateLimiting; 9+builder.Services.AddRateLimiter(options => 10+ options.AddConcurrencyLimiter("ConcurrencyPolicy", limiter => 11+ { 12+ limiter.PermitLimit = 2; 13+ limiter.QueueLimit = 25; 14+ limiter.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; 15+ })); 16+builder.Services.AddOpenApi(options => // only if tooling cannot read 3.2 yet 17+ options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_1); 18 19 var app = builder.Build(); 20-app.UseConcurrencyLimiter(); 21+app.UseRateLimiter(); 22+app.MapGet("/", () => "Hello World!").RequireRateLimiting("ConcurrencyPolicy");
Elsewhere in the .NET 11 list, x64 now requires x86-64-v2, adding SSE4.2 and POPCNT to the baseline, so a very old VM fails at startup with a missing-instruction-set message. When a BackgroundService fails under StopHost, IHost.RunAsync now rethrows instead of letting the process exit with success; Microsoft recommends doing nothing, and it is right. DateOnly.TryParse and TimeOnly.TryParse throw ArgumentException for invalid DateTimeStyles instead of returning false. On the SDK side, local container builds prefer platform-native runtimes before Docker, dnx scripts bypass global.json, and restore no longer searches the global packages folder for a higher version.
Twenty-four months, and the road from .NET 10
The release index ends .NET 11 support on November 14, 2028, the same day as .NET 10 LTS (released November 11, 2025). .NET 8 LTS and .NET 9 STS both leave support today. Counted from GA, that is 36 months for .NET 8 and .NET 10, and 24 for .NET 11.

Moving from 10 to 11 therefore buys features, not time. If you go:
- Change
TargetFrameworkfromnet10.0tonet11.0, once inDirectory.Build.propsif you have one; C# 15 comes with it. - Pin the SDK with the global.json below;
latestFeatureaccepts later 11.0 feature bands and patches. - Move images to
mcr.microsoft.com/dotnet/sdk:11.0andaspnet:11.0. The defaultaspnet:11.0tag is Ubuntu 26.04, with Alpine 3.24 and Azure Linux 3.0 variants, so check anyapt-getlines. - In GitHub Actions,
actions/setup-dotnetinstalls the global.json version whendotnet-versionis omitted; setglobal-json-fileif the file is not at the root. - Grep for types named
unionorclosedand for[with(, then build with warnings as errors. - Replace ConcurrencyLimiter, choose OpenAPI 3.1 or 3.2, and update EF Core packages and the
dotnet-eftool to 11.0.0. - Run integration tests that exercise host shutdown, and confirm your x64 hosts meet x86-64-v2.
1{ 2 "sdk": { 3 "version": "11.0.100", 4 "rollForward": "latestFeature" 5 } 6}
The 30,000-foot read
.NET 11 is a release about closing things. Unions and closed hierarchies close the old gap with F# and TypeScript for modeling values that are one of a known set; Zstandard closes a gap the ecosystem filled with native wrappers; runtime async begins to close the distance between the code you write and the stack you debug. None of it is spectacular, which is its virtue. The breaking changes are mostly the price of new keywords and old deprecations finally collected.
The calendar is the part you cannot negotiate with. With STS at 24 months, .NET 10 and .NET 11 expire together, and the old habit of skipping odd releases has lost its arithmetic. The remaining question is whether unions, in-box zstd and cleaner stacks justify one more upgrade before November 2028. For a service that models domain states with marker interfaces and default arms, probably yes. Watch whether runtime async sheds its preview label in .NET 12; that is where the performance story will be told.
Sources: .NET 11 release metadata, dotnet/core (GA date, SDK 11.0.100, STS, RC2 and RC3 dates); .NET 11.0.0 release notes (Visual Studio 18.12, Docker images, dotnet-ef 11.0.0); dotnet/core releases index (end-of-support dates for .NET 8, 9, 10 and 11); .NET Conf 2026 (November 10 to 13 launch event); .NET Blog (no GA announcement post yet); Announcing .NET 11 RC1 (unions stabilized); What's new in .NET 11 (feature overview, process APIs); What's new in C# 15 (unions, closed, collection arguments, extension indexers, labeled loops, memory safety preview); .NET 11 runtime (runtime async, stack traces, JIT); .NET 11 libraries (Zstandard, LINQ joins, decimal types, HTTP content); System.IO.Compression reference source (Zstandard signatures); ASP.NET Core 11 (unions, zstd middleware, OpenTelemetry, OpenAPI 3.2); EF Core 11 (FullJoin, MaxByAsync, VectorSearch, migrations); Roslyn breaking changes for .NET 11 (compiler changes and fixes); .NET 11 breaking changes (runtime, library and SDK list); Minimum hardware requirements (x86-64-v2); IHost.RunAsync change (BackgroundService failures); DateOnly and TimeOnly TryParse change (ArgumentException); ASP.NET Core 11 breaking changes (22 entries); ConcurrencyLimiter removed (rate limiter migration); OpenApiVersion defaults to 3.2 (pinning 3.1); dotnet-docker aspnet README (11.0 tags, Ubuntu 26.04); global.json docs (rollForward); setup-dotnet action.yml (global.json inputs). CAVEAT: GA status rests on the dotnet/core metadata, release notes and container tags dated November 10; the devblogs announcement had not been published when checked, and the 11.0.0 release notes still list their CVE entries as "TBD". The Learn overview was last revised for RC2, the EF Core 11 page still calls the release "in development", and the ASP.NET Core breaking-change list is dated September 29, so details may shift. Runtime async for user code, C# memory safety and EF Core VectorSearch are preview or experimental. Support months are computed from official GA and end-of-support dates. Corrections to earlier coverage: GA followed an RC3, not RC2; runtime async is not yet a stable opt-in for application code; Zstandard now sits in the System.IO.Compression namespace. No vendor performance figures are cited because no .NET 11 performance post was found.