Common Issues When Upgrading to .NET 9
By Kamlesh Bhor Β· π 08 Sep 2025 Β· ποΈ 9
Common Issues When Upgrading to .NET 9 β A Step-by-Step Guide
Upgrading to the latest .NET version always feels exciting β better runtime performance, new language features, improved trimming/AOT, and modern cloud-native support. But letβs be honest: upgrades also bring surprises β build errors, runtime changes, or third-party libraries not ready for the new framework.
When I upgraded my projects to .NET 9, I hit multiple roadblocks. Some were minor warnings, others were runtime crashes that took hours to figure out. Thatβs why I wrote this step-by-step guide, so you can learn from my mistakes and upgrade smoothly.
π Quick fact: .NET 9 is a Standard-Term Support (STS) release (18 months of support). Itβs focused on performance, trimming/AOT improvements, and cloud-native workloads.
π Official .NET 9 overview
π¨ Common Problems Youβll Likely Face
-
SDK / toolchain mismatch between dev machine, CI, and Docker images.
-
BinaryFormatter removed β legacy serialization code just breaks.
-
EF Core 9 changes β pending migrations now throw at runtime.
-
ASP.NET Core tweaks (
MapStaticAssets
, proxy headers). -
Third-party NuGet packages lagging behind.
-
Trimming/AOT surprises when reflection-heavy code disappears in publish.
Step 1 β Update Your Environment
The first upgrade mistake I made was only updating my local SDK but forgetting CI/CD agents. Always start with the environment:
-
Install the .NET 9 SDK everywhere.
-
Pin the SDK with
global.json
:
{
"sdk": {
"version": "9.0.x",
"rollForward": "disable"
}
}
-
Update Docker images:
-
Confirm versions:
π More info: Upgrade to .NET 9 guide
Step 2 β Update Project Files
Open each .csproj
and bump your target framework:
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
If you multi-target, add net9.0
inside <TargetFrameworks>
.
Then run:
dotnet restore
dotnet build
Step 3 β Update Dependencies
The next thing I ran into: NuGets not supporting net9.0
.
Run:
dotnet list package --outdated
-
Update Microsoft packages (ASP.NET Core, EF Core, Extensions) first.
-
Then check third-party packages β some might not yet support .NET 9.
-
If stuck: replace them, use a compatibility shim, or hold production upgrade until stable.
Step 4 β Breaking Changes (The Big Pain Points)
π Full list: Breaking changes in .NET 9
BinaryFormatter is Gone
Any code using it will break. For example:
// Old way (removed)
var bf = new BinaryFormatter();
using var ms = new MemoryStream(bytes);
var obj = (MyDto)bf.Deserialize(ms);
// New way (safe)
var obj = JsonSerializer.Deserialize<MyDto>(Encoding.UTF8.GetString(bytes));
API Overloads
Some string
/Span
overloads now conflict β you may need explicit casts.
Runtime Behavior
Float-to-int conversions behave differently in JIT β test number-sensitive logic.
Step 5 β ASP.NET Core Changes
π See: ASP.NET Core in .NET 9
-
Static files: new
MapStaticAssets()
in templates (with fingerprinting). Stick withUseStaticFiles()
if you host custom static content. -
Proxy headers: changes to forwarded headers β double-check reverse proxy setups.
-
Blazor: reconnection and SignalR serialization tweaks β test carefully.
Step 6 β EF Core 9 Pitfalls
π See: EF Core 9 Breaking Changes
-
Migrations: calling
Migrate()
now throws if there are pending model changes. -
Transactions: EF wraps
Migrate()
in a transaction β if you wrapped it already, expect conflicts. -
Cosmos DB: discriminator/JSON mapping changed.
-
Sync I/O: Cosmos now throws on sync calls β go async.
Step 7 β Trimming & AOT Surprises
If you publish with trimming:
dotnet publish -c Release -p:PublishTrimmed=true
Reflection-based code can vanish.
Fix it with [DynamicDependency]
, source generators, or configuration files.
π Trimming in .NET 9
Step 8 β CI/CD & Hosting
-
Update pipeline agents with .NET 9 SDK.
-
Update Docker
FROM
images. -
Verify hosting platform (Azure App Service, Functions, AWS, etc.) supports .NET 9.
Step 9 β Testing & Rollout Strategy
-
Run unit, integration, and end-to-end tests on
net9.0
. -
Use canary deployments β push one service first, monitor, then roll out.
-
Always have a rollback plan.
π Benchmarking .NET 8 vs .NET 9
One of the main reasons to upgrade is performance. .NET 9 brings improvements in JIT, GC, and async handling β but how much does it matter in practice? Letβs run a quick benchmark.
I used BenchmarkDotNet to compare a simple JSON serialization and string processing task in .NET 8 vs .NET 9.
Sample Benchmark Code
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Text.Json;
public class SerializationBenchmarks
{
private readonly MyDto _dto = new MyDto { Id = 1, Name = "Kamlesh", Value = 123.45 };
[Benchmark]
public string Serialize()
{
return JsonSerializer.Serialize(_dto);
}
[Benchmark]
public MyDto Deserialize()
{
var json = JsonSerializer.Serialize(_dto);
return JsonSerializer.Deserialize<MyDto>(json)!;
}
[Benchmark]
public string StringConcat()
{
string result = "";
for (int i = 0; i < 1000; i++)
result += "dotnet";
return result;
}
}
public class MyDto
{
public int Id { get; set; }
public string Name { get; set; }
public double Value { get; set; }
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<SerializationBenchmarks>();
}
}
Run it on both .NET 8 and .NET 9.
Results (Sample Output)
Benchmark | .NET 8 Mean Time | .NET 9 Mean Time | Improvement |
---|---|---|---|
Serialize DTO | 420 ns | 360 ns | ~14% faster |
Deserialize DTO | 1,200 ns | 1,050 ns | ~12% faster |
StringConcat (1k) | 55 ΞΌs | 47 ΞΌs | ~15% faster |
π The exact numbers vary depending on your machine, but the trend is clear: .NET 9 consistently outperforms .NET 8 in common tasks.
Why This Matters
-
Serialization and string operations are common in APIs β so youβll feel the gains directly.
-
Multiply these improvements across thousands of requests, and you get better throughput + lower latency in production.
-
Combine with .NET 9βs trimming/AOT, and you also reduce app size + startup time.
β Quick Pre-Production Checklist
-
All machines/CI on same SDK (
global.json
). -
All NuGets updated.
-
No
BinaryFormatter
. -
EF Core migrations applied.
-
Trimming/AOT validated.
-
Smoke tests pass.
-
Rollback plan ready.
Β
π FAQs
Q: Should I upgrade right away?
If you need new features and performance β yes. For long-term stability, you might wait for the next LTS.
Q: My app still uses BinaryFormatter, what now?
Migrate to System.Text.Json
or Protobuf. Create a migration tool for old data.
Q: EF migrations broke, why?
Because EF Core 9 enforces pending migrations. Add migrations before calling Migrate()
.
π― Conclusion
Upgrading to .NET 9 doesnβt have to be stressful. Most of the headaches β BinaryFormatter removal, EF Core migrations, ASP.NET tweaks β are solvable once you know where to look.
This guide gives you a field-tested upgrade path:
-
Beginners can follow the steps confidently.
-
Experts get deeper coverage of trimming, EF Core, and CI/CD.
With proper testing and rollback planning, youβll be running on .NET 9 smoothly β and ready to enjoy its performance and modern features right away.

Article by Kamlesh Bhor
Feel free to comment below about this article.
π¬ Join the Discussion