What's the difference between the new netstandardapp and netcoreapp TFMs?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The short answer is that netcoreapp is a real application target framework, while netstandardapp was a historical, transitional idea from the early .NET Core and project.json era rather than a long-term target developers should build around. In current .NET work, you should think in terms of netstandard for broadly reusable libraries and netcoreapp or modern netX.Y TFMs for runnable applications.
What a TFM Is Meant to Communicate
A Target Framework Moniker tells the build tools which API surface and runtime family your project expects. It answers questions such as:
- is this project a runnable application or a reusable library
- which APIs are available at compile time
- which runtime families can consume the output
That is why small differences in TFM naming matter so much. They change compatibility and deployment expectations.
What netcoreapp Means
netcoreapp is the application TFM for .NET Core-era applications. Historically, it meant “this project runs on the .NET Core runtime and can use the full application model available there.”
A simple SDK-style example looked like this:
In later .NET releases, the naming moved forward to net5.0, net6.0, net8.0, and so on, but the idea is the same: application TFMs target a concrete runtime.
What netstandardapp Was
netstandardapp appeared during the old project.json transition period as an attempt to describe application targeting built on .NET Standard plus application-specific behavior. It was never the long-term TFM that most developers should have standardized on.
That is why modern documentation and tooling discussions focus on:
- '
netstandardfor reusable cross-runtime libraries' - '
netcoreappfor .NET Core applications in the .NET Core era' - '
netX.Yfor modern unified .NET applications and libraries'
So if you encounter netstandardapp in an old post, treat it as historical context, not as a target you should choose for new code.
The Real Library Versus Application Distinction
The concept that matters more than the old name is this:
- '
netstandarddescribes a shared API contract for libraries' - '
netcoreappor later concrete runtime TFMs describe actual runnable environments'
A library might target netstandard2.0 so that multiple .NET implementations can consume it.
An application should target a runtime-capable TFM instead.
That separation is still the right way to think about project targeting today.
How to Read Old Guidance Safely
If you are reading older migration guides or archived discussions, translate them into current terms:
- old
netcoreappexamples still map conceptually to runtime-specific targets - old
netstandardappreferences are usually artifacts of the transition period - new applications should use current
netX.YTFMs, not resurrect old names
This matters because cargo-culting historical TFMs into a modern SDK-style project leads to confusion fast.
Choosing a TFM Today
For current codebases, a simple rule usually works:
- target
netstandardonly if you truly need broad library compatibility with older or multiple .NET consumers - target current
netX.Yfor most new applications - target current
netX.Yfor libraries too if you only support modern .NET
That guidance is far more useful than trying to reason about netstandardapp as if it were still an active mainstream choice.
Common Pitfalls
A common mistake is reading a very old blog post and assuming netstandardapp is still a current application target. It is not the practical path for modern projects.
Another mistake is using netstandard for an application project. netstandard is a library contract, not a runnable app target.
It is also easy to over-target for compatibility. If your consumers are all on modern .NET, using the latest supported concrete TFM is often simpler than chasing historical compatibility layers.
Summary
- '
netcoreappwas the real application TFM for .NET Core-era applications.' - '
netstandardappwas historical transitional vocabulary, not a long-term mainstream target.' - The modern distinction is still library contract versus concrete runtime target.
- Use
netstandardonly when broad library compatibility is genuinely required. - For new applications, target current
netX.Yrather than old transitional TFMs.

