Choosing a .NET target framework
The TargetFramework (TFM) you pick determines which runtime, API surface, and support window a project gets. Choose it from the published support cadence, not from habit. State the exact version and its end-of-support date in the project so the decision is auditable and reversible.
Support cadence (pinned: .NET support policy, verified 2026-06-09)
.NET ships a major version every November. Support tiers:
- LTS (Long Term Support) — even-numbered releases, supported 3 years.
- STS (Standard Term Support) — odd-numbered releases, supported 24 months (extended from 18 starting with .NET 9).
Current versions and end-of-support dates (per the support policy reference):
| Version | Tier | Released | End of support |
|---|---|---|---|
| .NET 10 | LTS | 2025-11-11 | 2028-11-14 |
| .NET 9 | STS | 2024-11-12 | 2026-11-10 |
| .NET 8 | LTS | 2023-11-14 | 2026-11-10 |
Note: .NET 8 (LTS) and .NET 9 (STS) both reach end of support on 2026-11-10, so neither is a durable target for new work as of 2026. Re-verify these dates against the reference URL — Microsoft updates them.
Requirements
- target-current-lts-for-apps: New applications and services SHOULD target the current LTS (
.NET 10/net10.0as of 2026-06-09) to maximize the support runway with predictable upgrades. - sts-only-when-needed: A project MAY target an STS release only when it needs an STS-exclusive feature AND the team commits to upgrading before the 24-month window closes. Otherwise prefer LTS.
- multi-target-libraries: A reusable library SHOULD multi-target the TFMs its consumers actually require (e.g.
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>), not the newest available. Add anetstandard2.0target only when a concrete consumer needs it. - pin-the-sdk: Every repo MUST pin the SDK with a
global.json("sdk": { "version": "10.0.x", "rollForward": "latestFeature" }) so local, CI, and agent builds resolve the same toolchain. - state-version-explicitly: The
TargetFramework(s)value MUST be explicit in the.csproj; do not rely on an implicit or inherited default. Do not assume "latest" — name the version. - avoid-eol-targets: A project MUST NOT newly target a framework whose end-of-support date has passed or is within the project's planned delivery window. Check the date before committing the TFM.
- separate-tfm-from-langversion: Treat
<LangVersion>as a separate decision from the TFM; raising the language version does not change the runtime or its support window.
Decision steps (for an agent)
- Re-read the support policy reference and confirm today's LTS/STS versions and dates.
- App or service: set
<TargetFramework>to the current LTS unless an explicit, documented STS need exists. - Library: set
<TargetFrameworks>to the union of consumer requirements; justify each TFM in a comment. - Add or update
global.jsonto pin the SDK feature band. - Record the chosen version and its end-of-support date in the PR description.
This keeps the choice a small, reversible decision (per agenticdevelopercookbook://principles/small-reversible-decisions): a TFM bump is a single property edit plus a rebuild.