.NET 11: The STS Release With C# 15 Union Types and Runtime-Async

.NET 11: The STS Release With C# 15 Union Types and Runtime-Async

The .NET release cycle has a rhythm now. Every November, a new major version ships. Odd years are STS (Standard Term Support), supported for two years. Even years are LTS, three years. The official release policy is explicit that “LTS and STS releases differ only by support duration. The .NET team follows the same software engineering and release processes for both.”

By that logic, .NET 11 should be a quiet release. Two years of support, faster pace, traditionally treated as the place where Microsoft prototypes the next LTS. Skip it.

That framing breaks down once you look at what’s already shipped in Preview 4. The union keyword has compiler support in Preview 2 and IDE integration in Preview 3. The runtime libraries themselves are now compiled with runtime-async. System.Diagnostics.Process has a substantial new API surface. EF Core 11 translates approximate-nearest-neighbor vector queries against SQL Server 2025. STS or not, the next LTS will inherit all of this. Pretending it isn’t relevant means walking into .NET 12 cold.

This is what the roadmap actually contains, with six months still to ship. Every claim below is sourced from the .NET repositories. No blog post speculation.

Where We Are Today

As of 2026-05-25, .NET 11 has a hard GA date of November 10, 2026 (announced in the .NET 11 release notes README), with two years of STS support carrying it through 2028-11-09. The 11.0.0 milestone in dotnet/runtime shows roughly a thousand open issues against nineteen hundred closed, and the cycle is on schedule.

Previews have shipped on the usual monthly cadence: Preview 1 on 2026-02-10, Preview 2 on 2026-03-10, Preview 3 on 2026-04-14, and Preview 4 on 2026-05-12. Preview 5 daily builds are already visible: dotnet/runtime issues reference SDK 11.0.100-preview.5.26261.101, but the official release notes for it haven’t been published yet. On the language side, the features marked “Working Set” in the Roslyn Language Feature Status target C# 15, and the Preview 4 C# notes link directly to the What’s new in C# 15 page.

Union Types: Discriminated Unions Are Actually Shipping

Discriminated Unions have been “the next big C# feature” since 2019. In .NET 11, they stop being a roadmap promise. They’re a preview feature you can compile against today.

The Preview 3 C# release notes put it plainly: “Compiler support for union types was added in preview 2. Preview 3 includes better IDE support for working with union types.” The official documentation points to csharp-15-union-types on the .NET blog and the C# 15 What’s new page. The catch in Preview 3 is that the runtime types UnionAttribute and IUnion still require polyfills inside System.Runtime.CompilerServices:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
        AllowMultiple = false)]
    public sealed class UnionAttribute : Attribute;

    public interface IUnion
    {
        object? Value { get; }
    }
}

Preview 4 fixes the polyfill problem. The .NET libraries release notes call out a section explicitly titled Discriminated-union scaffolding in System.Runtime.CompilerServices: the runtime side of unions is moving from polyfill into the BCL.

In parallel, closed class hierarchies (the metadata foundation for exhaustive pattern matching against sealed hierarchies) are tracked as merged-as-preview into .NET 11 Preview 5 and VS 18.8. Together with union, these form the discriminated-union story C# users have been asking for since the language got pattern matching. If you’ve been writing OneOf<T1, T2> libraries, sealed-class hierarchies, or abstract record discriminators, this is the cycle when those patterns start being supported by the language and metadata, not just by a third-party NuGet.

Runtime Async: Not Future, Present

The runtime-async work is no longer a preview-of-a-preview. From the Preview 4 runtime release notes:

The runtime libraries are now built with runtime-async=on. That means that the runtime libraries do not contain compiler-generated state machines, but rely on the runtime-provided async feature. Enabling runtime async for all runtime libraries provides excellent functional and performance testing.

This is enormous. The runtime libraries (the same code you depend on transitively in every .NET project) are now compiled with the new async model. Whether you opt in to runtime-async in your own code or not, your dependencies already are. The change builds on Preview 3, which removed the [RequiresPreviewFeatures] opt-in for runtime-async. Preview 4 then closed two gaps that had been blocking everyday use: covariant TaskTask<T> overrides (runtime #125900, #126768), and runtime-async method inlining in crossgen2 so Ready-to-Run compilation no longer refuses to inline async fast-paths (runtime #125472).

ASP.NET Core ships the matching piece in Preview 4: Runtime-async enabled for shared framework libraries. The whole shared framework (runtime plus ASP.NET Core) now uses the runtime-provided async machinery. The Roslyn test plan (roslyn #75960) notes that runtime-async was “included in .NET 10 (feature in preview)”. .NET 11 is the cycle that takes it from preview-with-opt-in to default for the standard library. .NET 12 LTS is where most teams will inherit it without thinking about it.

If you maintain a high-throughput service, allocate Task instances in hot paths, or fight with ConfigureAwait(false) discipline: start reading about this now, not after .NET 12 ships.

Process Gets a Major API Expansion

The Preview 4 libraries release notes lead with a section worth quoting: "System.Diagnostics.Process picks up a substantial set of new APIs in Preview 4, covering common scenarios where developers previously had to fall back to manual Process plumbing or P/Invoke."

What’s actually shipping is the one-shot orchestration surface every CLI-touching project has been hand-rolling forever. Process.Run, Process.RunAsync, Process.RunAndCaptureText, Process.ReadAllText, Process.ReadAllBytes, and their async variants give you single-call process invocation with output capture, replacing the OutputDataReceived / ErrorDataReceived wiring most of us learned to write once and copy forever (runtime #127210, #126807, #126942). For streaming output line by line, Process.ReadAllLinesAsync now returns a ProcessOutputLine struct that distinguishes stdout from stderr without string parsing (runtime #126987).

The lifecycle story is just as thorough. Process.StartAndForget, ProcessStartInfo.StartDetached, and KillOnParentExit cover fire-and-forget and parent-tied launches (runtime #126078, #126632, #126699). SafeProcessHandle picks up Start, ProcessId, Kill, Signal, and the WaitForExit* family for handle-driven control without going through a Process instance (runtime #126192, #126313, #127022). Handle inheritance becomes precise rather than all-or-nothing through ProcessStartInfo.InheritedHandles and the new StandardInputHandle / StandardOutputHandle / StandardErrorHandle SafeFileHandle properties (runtime #126318, #125848).

The end result reads like the helper everyone keeps in a Utilities namespace, now in the BCL:

using System.Diagnostics;

ProcessTextOutput result = await Process.RunAndCaptureTextAsync(
    "git", ["status", "--porcelain"]);

Console.WriteLine(result.StandardOutput);
Console.WriteLine($"exit code: {result.ExitStatus.ExitCode}");

That single API replaces a category of code that has been duplicated across the .NET ecosystem for fifteen years.

ASP.NET Core 11: Concrete Features, Not Roadmap Marketing

The aka.ms/aspnet/roadmap link redirects to dotnet/aspnetcore#64787, where the body honestly says:

ASP.NET Core planning for .NET 11 is now in progress! This roadmap is currently just a placeholder. We’ll update the roadmap with specific planned features as planning progresses.

So the roadmap document is empty. What’s actually shipping is in the preview release notes. The Preview 4 ASP.NET Core notes include real, finished work: OpenAPI document generation now recognizes the proposed HTTP QUERY method (a safe, idempotent verb with a request body, useful when a query is too large for a URL) and emits it correctly for endpoints registered with MapMethods("/search", ["QUERY"], ...) (aspnetcore #65714). MCP server scaffolding ships straight from dotnet new, putting Model Context Protocol templates in the official SDK. Blazor Server gains server-initiated circuit pause so a server can suspend memory until the client reconnects. Kestrel exposes TLS handshake observability events for diagnostics. And Blazor WebAssembly publish output continues to shrink, preview after preview.

The honest “roadmap” approach to ASP.NET 11 is: read the preview release notes. The roadmap document won’t tell you anything the previews don’t tell you faster.

EF Core 11: Vector Search and JSON Maturity

EF Core 11’s headline in Preview 4 is approximate vector search against SQL Server 2025 (efcore #38075): EF Core now translates approximate nearest neighbor (ANN) vector queries, with WithApproximate() triggering the WITH APPROXIMATE clause introduced in SQL Server 2025. Underneath that headline, JSON mapping has finally been integrated fully into the relational model: JSON columns are first-class participants in the query pipeline rather than a side-attached feature. Temporal period properties can now be projected onto CLR properties, cleaning up C#-side modeling of temporal tables. And dotnet ef reads defaults from a dotnet-ef.json file, ending the era of sprinkling --context and --startup-project onto every command.

The follow-the-AI-trend item is vector search. The follow-the-ergonomics-trend item is dotnet-ef.json. Both ship in the same preview. Fair coverage.

SDK and CLI

The Preview 4 SDK notes continue the thread I picked up in .NET CLI 10 – Microsoft Finally Realizes DevOps Exists. dotnet watch now mirrors dotnet run’s device-picker flow for MAUI and mobile targets. Fish shell completions land at parity with Bash, Zsh, and PowerShell. OpenTelemetry replaces Application Insights for CLI telemetry, so the dotnet command now emits OTel signals to anyone who wants to collect them.

More forward-looking: the SDK lays the foundation for a NativeAOT-compiled dotnet driver. Faster startup is the long game; Preview 4 doesn’t ship the AOT-driver itself, but the entry point has been carved out. Partial Ready-to-Run for upstack tooling continues to shrink SDK archive size. The direction set in .NET 10 (DevOps-grade ergonomics, machine-readable output, container-aware defaults) is consolidating, not reinventing.

The C# 15 Working Set

Beyond union, the Roslyn working set currently targeting C# 15 includes the following features. Status verified against the doc on 2026-05-25:

FeatureStatusWhat it gives you
UnionsCompiler in p2, IDE in p3Discriminated union types via the union keyword
Closed class hierarchiesMerged as preview (p5 / VS 18.8)Foundation for exhaustive switch
Unsafe evolutionMerged as preview (p2 / VS 18.6)API contract evolution in unsafe contexts
Collection expression argumentsMerged (p1 / VS 18.4)Constructor args inside [...] literals
Dictionary expressionsIn progress[key1: value1, ...] literal syntax
Extension indexersIn progressIndexers on C# 14 extension members
Labeled break/continueIn progressbreak outer; / continue loop;
Null-conditional awaitIn progressawait? short-circuit on null
Chained relational comparisonIn progressa < x < b
Target-typed static member accessIn progressDrop type names in static contexts
Relax modifier orderingIn progressstatic public accepted
Compound assignment in initializersIn progress+= inside object initializers
Extension members on typeless receiversIn progressWider applicability of C# 14 extensions

Working-set items are not guaranteed to ship: Microsoft routinely defers features that haven’t stabilized, and that’s what working sets are for. But every entry above has a feature branch, an assigned developer, reviewers, and a Roslyn test-plan issue. The pipeline is real.

The STS Question: Should You Adopt?

The honest answer depends on what you ship.

Adopt the preview now if you publish NuGet libraries and need to validate them against the runtime-async-enabled BCL, if you run high-throughput services where runtime-async could materially change allocation profiles and you have the ops headroom to A/B it, if you build Roslyn-based tooling and want to be ready for C# 15 and union types before they land, or if you’re prototyping anything that benefits from discriminated unions or closed class hierarchies (DDD aggregates, message handlers, parser ASTs).

Adopt at GA in November 2026 if you’re starting a greenfield project with a two-year-plus horizon, if you’re standing up internal services where the .NET 11 → .NET 12 LTS upgrade path is part of the original plan, or if you simply want C# 15 features in production before the next LTS forces it.

Stay on .NET 10 LTS if you’re in a regulated environment where STS support windows don’t pass procurement, if you maintain a large LOB monolith with deferred upgrade muscle, or if “this is a critical system, we run boring software” is a strategy statement you stand behind.

The bad answer is to ignore .NET 11 entirely. Even if you stay on the LTS, what ships in .NET 11 (union, runtime-async-as-default, the Process API, EF Core’s JSON-and-vector story) is what your team will inherit when the next LTS lands. “I’ll learn it when LTS forces me” is twelve months of accumulated technical debt waiting to happen.

How to Track Without Drowning

Avoid the blog post firehose. The canonical source is the dotnet/core/release-notes/11.0 directory: one file per preview, broken down by component. Read it first. After that, filter dotnet/runtime issues by milestone 11.0.0 and pay attention to area-VM-coreclr, area-CodeGen-coreclr, area-System.Threading.Tasks, and tenet-performance. Skim the Roslyn working set once a month: the state column tells you what shipped and into which preview. For new APIs specifically, api-ready-for-review is the label to watch on dotnet/runtime issues.

The .NET Blog ships one post per preview. Skim the headlines, click only when something matters. What I deliberately don’t follow: LDM meeting notes (too noisy), individual PR threads (too granular), and Twitter speculation about features that haven’t been merged into a feature branch.

Verdict

.NET 11 is the most substantive STS release I can remember in the .NET Core era. Union types in C# 15, with compiler support in Preview 2 and IDE integration in Preview 3, close out an eight-year language-design conversation. Runtime-async by default in the BCL and ASP.NET Core shared framework changes the allocation profile of every async-heavy application without a source change. The Process API expansion removes a category of hand-rolled CLI orchestration code from every codebase that has ever shelled out. EF Core’s vector search and JSON integration raise the floor on what an LOB EF Core stack can do without leaving the ORM.

The cycle says STS releases are for library authors and early adopters. The contents say otherwise. If you build .NET software in 2026 (even on .NET 10 LTS), the work landing in .NET 11 is what your code will be running on by November 2027 at the latest. Read the previews now, not at GA.

The STS / LTS rhythm is a support-window decision, not a relevance decision. .NET 11 is shipping the runtime and language work that will define the next LTS.

Comments

VG Wort