.NET Versions Explained: LTS vs STS and Which to Choose

Confused by .NET LTS vs STS? See the release calendar, support windows, and a decision framework for picking the right .NET version for your project.

Executive Summary: Modern .NET ships one major version every November, and each one carries a label: Long Term Support (LTS) or Standard Term Support (STS). The quality is identical; the only real question in .NET LTS vs STS is how long you keep getting patches, and therefore how often you must upgrade.

Put a recurring reminder in your calendar right now: on November 10, 2026, both .NET 8 and .NET 9 stop receiving security patches on the same day. The November before an end-of-support month is when rushed migrations happen, with deploys frozen, third-party packages lagging, and a security review asking why production runs an unsupported runtime. Nothing about that date is a surprise; it has been published for years.

The choice of .NET LTS vs STS is a choice between two support windows for the same product. LTS releases receive three years of free patches and servicing. STS releases receive two. The quality is identical; Microsoft’s own policy page states that the only difference between them is the length of support. The label decides when you must upgrade, not how well the code runs.

The dates below are verified against Microsoft’s .NET support policy. The article assumes .NET SDK 10.0 with C# 14, but the decision framework applies to any modern .NET, version 8 or later. If you have not installed anything yet, start with installing the .NET SDK, which covers every operating system.

After a decade of steering these upgrades, my default is clear: default to the current LTS, ignore the “newer is better” pull, and schedule the next major as routine maintenance while the current one still has a year of support left. Teams that internalize that never meet an end-of-support deadline in a panic. Teams that don’t, do.

The release cadence: one major .NET every November

Modern .NET releases one major version each November, alternating support labels by year. STS releases land in even-numbered years, LTS releases in odd-numbered years. .NET 11, due in November 2026, will be STS. .NET 12, due in November 2027, returns to LTS. Patches arrive monthly on Patch Tuesday (the second Tuesday) and are guaranteed compatible within a major. Patches fix and harden, they never change behavior or remove APIs. New features land only in the yearly major.

The C# compiler rides the same train. C# 14 shipped with the .NET 10 SDK, and the next C# version arrives with the next major. If you need a language feature, the major version decides whether it exists, not the support label.

Support windows at a glance

Here is the calendar that drives every version decision, straight from the support policy (as of November 2025):

Version Released Type End of support Support phase now
.NET 10 November 11, 2025 LTS November 14, 2028 Active
.NET 9 November 12, 2024 STS November 10, 2026 Active
.NET 8 November 14, 2023 LTS November 10, 2026 Active

Two details hide in that table. First, releases move through phases: Active support means full fixes, then a release enters Maintenance in its final stretch before end of support. Second, staying supported means staying current: the policy requires that systems remain on released patch updates, so “we support .NET 10 but skipped the last six patches” is out of policy. The pattern repeats every two years:

        Nov 2023     Nov 2024     Nov 2025     Nov 2026     Nov 2027
        .NET 8       .NET 9       .NET 10      .NET 11      .NET 12
        LTS          STS          LTS          STS          LTS
EOL:    Nov 2026     Nov 2026     Nov 2028     Nov 2028     Nov 2030

What the LTS label does and does not mean

The most persistent myth in the .NET community is that LTS releases are more stable or better tested than STS releases. They are not. The support policy says it in plain words. The quality of all releases is exactly the same, the only difference is the length of support. There is no separate LTS build pipeline; there is no extra hardening pass.

WRONG: “We wait for the LTS because it’s more stable than the STS.”

RIGHT: “We target the LTS because we want a three-year runway before our next forced upgrade, not because the code is different.”

What the label actually buys you is calendar. An STS project commits to upgrading at least every two years, and in practice every year if it wants to stay comfortably inside support. An LTS project buys three years, and smart teams still upgrade on a two-year rhythm so they never sit in the final months of a window where a surprise blocking bug leaves no escape. What the label never buys you is bug-free code: every major, LTS or not, needs its Patch Tuesday updates.

Which .NET version should you choose?

Your situation Pick Why
New service, tool, or application Current LTS (.NET 10) Longest support runway, monthly patches, the version most documentation and libraries target
You need a feature that only exists in the newest STS That STS Features ship only in majors; accept the short runway and plan the hop to the next LTS
Existing app on .NET 8 Move to .NET 10 before November 10, 2026 .NET 8 and .NET 9 both reach end of support that day
Library consumed by teams you don’t control netstandard2.0, or multi-target Consumers stay free to choose their runtime; you don’t force upgrades on them
A throwaway spike that dies in a month Whatever is installed Support windows are irrelevant to code that never ships

TargetFramework, the SDK, and global.json

Three different numbers get confused constantly, and separating them prevents most build weirdness:

  • TargetFramework (in your .csproj) is the runtime your code compiles for: net10.0, net8.0, and so on. The full list of target framework monikers is documented in the TFM reference.
  • The installed SDK is the toolchain doing the compiling. A .NET 10 SDK happily builds net8.0 projects, so a newer SDK never forces a newer target.
  • Runtime roll-forward picks the patch at execution: an app targeting net10.0 runs on the latest installed 10.0.x patch, so Patch Tuesday needs no recompile. Rolling forward across a major version is opt-in configuration, not default behavior.
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
  </PropertyGroup>
</Project>
{
  "sdk": {
    "version": "10.0.100",
    "rollForward": "latestFeature"
  }
}

The first file pins what your app runs on. The second, global.json, pins which SDK feature band builds it, so two machines cloning the same repo compile with the same toolchain. The global.json reference covers the roll-forward modes.

The upgrade path: one major at a time

Upgrading from .NET 8 to .NET 10 is two majors in one jump, and that is normal. You are not required to step through every STS on the way. The flow:

  1. Change TargetFramework to net10.0 and rebuild.
  2. Fix the warnings the retarget surfaces (nullable annotations and API changes are the usual suspects).
  3. Update package references that align with the runtime: EF Core majors follow .NET majors, so EF Core 10 goes with .NET 10. If the data layer is new to you, start from getting started with EF Core code-first.
  4. Run the full test suite and ship behind a canary, a slot, or whatever incremental deploy you already trust.

Microsoft also ships upgrade-assistant as a global tool that walks projects through the retarget. It helps on large solutions, but a small service usually upgrades faster by hand. The teams that find upgrades painful are the ones that let two or three majors pile up between attempts, because then every dependency moves at once. Annual majors are small by design.

How real systems do this

  • Standardize on the current LTS. Mature teams pick the LTS and put the next major upgrade on the roadmap roughly 12 months before end of support, when the next LTS is stable but the deadline is still far away.
  • Let tooling catch EOL drift. Vulnerability and dependency scanners flag out-of-support runtimes and base images in CI, so a forgotten upgrade fails a build instead of an audit. The guide on CI/CD pipelines for .NET projects shows where such checks live.
  • Pin versioned base images. Container deployments build from versioned SDK and runtime tags, never latest. As a result, an image rebuild can never silently change your .NET version. dockerizing a .NET application covers the tag strategy.
  • Verify platform availability before committing. If you deploy to Azure App Service, confirm the runtime stack for your target version is available in your region before you plan a cutover. The guide on deploying .NET apps to Azure App Service goes through the checks.

A pattern I have seen more than once is the EOL-quarter migration. A team on .NET 6 schedules the 6-to-8 upgrade for October 2024 because “it’s the last chance”, then discovers a key library still has no net8.0-compatible release and the migration lands as a hot, pressured branch. The lesson that stuck with me: the upgrade itself was easy; the wait until the deadline was what made it hard. Teams that upgrade a year early find the same work spread over calm weekends.

Decision framework: choosing your support window

  1. Can your team ship an upgrade within a quarter when asked? If no, take the LTS. A short runway plus a slow team is how EOLs get missed.
  2. Does the feature you need exist in the current LTS? If yes, you are done: take the LTS. If a required API or runtime behavior exists only in the newest STS, take the STS knowingly.
  3. Do external policies demand supported runtimes? Regulated environments usually do. Staying inside a support window is then non-negotiable, and LTS gives the longest in-policy runway.
  4. Are you building a library? Optimize for consumers: target netstandard2.0 or multi-target the majors your users actually run, and never force an upgrade on them.
  5. Is the code short-lived? Spikes and demos can ride any installed SDK. Support windows do not apply to code that dies in a month.

When NOT to follow the LTS default

  • When an STS-only feature is the product. If your release depends on an API that only exists in .NET 11, waiting a year for .NET 12 helps nobody. Take the STS, and put the .NET 12 retarget on the calendar immediately.
  • When consumers pin you. A shared library used by ten apps still on .NET 8 must not jump to net10.0 alone. Multi-target the library and let each consumer upgrade on its own schedule.
  • When a deployment freeze blocks upgrades. If you cannot ship before an EOL, the answer is to negotiate the freeze for security patches, not to sit silently on an unsupported runtime. Patches inside a supported major are compatible, so staying current rarely touches the freeze.

Common mistakes

  • Treating LTS as “more stable”. Build quality is identical across labels. Only the support length differs, so “we wait for the LTS to avoid bugs” is waiting for nothing.
  • Ignoring the November 2026 double EOL. .NET 8 and .NET 9 both end on November 10, 2026; teams on either need a plan now, not in November.
  • Confusing TargetFramework with the installed SDK. The SDK is the compiler toolchain and builds older targets. You can install .NET 10 today without retargeting a single project.
  • Skipping patch updates inside a supported major. The policy requires staying current on patches, and the patches are compatible. Falling behind is both risky and out of policy.
  • Upgrading the SDK repo-wide without global.json. Different machines then build with different feature bands, and “works on my machine” returns; pin the SDK.
  • Multi-targeting everything. Every extra target framework is a build and test matrix you maintain forever. Target the runtimes you actually support.

Key takeaways

  • .NET ships one major every November: STS in even years (2-year support), LTS in odd years (3-year support).
  • Quality is identical between labels; the support window is the only difference, and it decides your upgrade cadence.
  • .NET 10 is the current LTS (until November 14, 2028); .NET 8 and .NET 9 both end support on November 10, 2026.
  • TargetFramework sets what you run on, the SDK compiles older targets fine, and global.json pins the build toolchain.
  • Upgrade majors on a schedule, a year before end of support, not in the EOL quarter.
  • Pick STS only when a missing feature justifies the treadmill, and multi-target libraries instead of forcing consumers to upgrade.

FAQ

What is the difference between LTS and STS in .NET?

Only the support length. LTS releases receive three years of patches, STS releases receive two, and Microsoft’s policy states the quality of all releases is exactly the same. An LTS label buys your team a longer runway between forced upgrades, not better code.

How long is .NET 10 supported?

.NET 10 is an LTS release published on November 11, 2025, with end of support on November 14, 2028. While it is supported, it receives monthly Patch Tuesday updates, and systems must stay current on those patches to remain in policy.

Is .NET 8 still supported?

Yes, but only until November 10, 2026, and the same date ends .NET 9. After that neither version receives security fixes. Apps on either should move to .NET 10 before that day arrives, ideally with months of slack.

How often should I upgrade .NET versions?

Ride the LTS train and plan one major upgrade roughly every two years, starting while your current version still has a year of support left. Teams on STS upgrade yearly by design, which is the trade-off they accepted for earlier access to features.

Which .NET version should I choose for a new project?

Target the current LTS, .NET 10, unless a specific feature you need exists only in the newest STS release. Libraries are the exception: target netstandard2.0 or multi-target so consumers choose their own runtime.

Choose the support window, not the headline version

Version numbers make headlines; support windows make release plans. The label next to a .NET release tells you nothing about quality and everything about your next two years of maintenance. Target the current LTS, keep the patch updates flowing, put the next major upgrade on the roadmap a year before it matters. Every guide in this series, from the .NET series index, will assume exactly that default. The rule of thumb: pick the support window that matches your upgrade appetite, and the version number takes care of itself.

Last updated on 12 October 2026

Share this article

Leave a Reply

Your email address will not be published. Required fields are marked *