.NET Development and Framework

Modern .NET is a platform on a release rhythm — not the static framework that some teams still imagine when they hear the name. Once you accept the LTS-and-STS cadence, almost every architectural conversation inside a .NET shop changes. Lifecycle planning becomes a quarterly topic. Major version migrations become routine rather than projects. And the question stops being “which version are we on” and becomes “what is our story for the next two.”

A recurring theme in this collection is evolution over time. The runtime, the BCL, and the SDK each move on their own track, and the interesting work happens at the seams. Dynamic PGO, tiered compilation, and the steady improvements to the JIT have changed what performance-sensitive code looks like — patterns that were defensible in .NET Framework era are now actively slower than the idiomatic version. Articles trace these shifts release by release rather than treating any single version as the canonical reference.

The BCL has been quietly transformed by additions like SearchValues<T>, FrozenDictionary, Span<T>, Memory<T>, and the surrounding ecosystem of ref struct types. These are not niche features — they are the new defaults for anyone writing hot-path code. Articles cover when reaching for them pays back, when the older API is still the right answer, and the surprising corners where they interact badly with closures, async, or older library boundaries.

SDK ergonomics deserve their own attention. Central Package Management, project-level PackageReference graphs, source generators, AOT, and the slow but real maturing of the workload model all shape what a maintainable solution looks like. Articles cover the project-system trade-offs that compound silently across a multi-year codebase.

The LTS/STS rhythm itself is treated as a planning concern. Articles cover how to schedule upgrades against a real release window, when to skip an STS release, and how to keep the upgrade muscle exercised so that the next migration is not the one that breaks things.

You're Shipping Bugs Faster, and Your Tests Are Helping

You're Shipping Bugs Faster, and Your Tests Are Helping

AI coding agents make you faster. They also make your bugs faster: they generate plausible-looking code, you review quickly, the tests pass, and production breaks two weeks later. I keep falling into this pattern myself, always on the happy path, telling myself the edge cases come later. They don’t. Here’s the pattern, why most test frameworks make it worse, and how TUnit fights it.
I'm Done Making Empty Promises

I'm Done Making Empty Promises

I’ve spent two articles in this series describing Past Self and the damage he left behind. What I haven’t said yet is the uncomfortable part: I am Past Self, right now, making the same promises he made. // TODO: fix this properly. We’ll clean that up after the release. I’ll write the tests when there’s time. This is the third part of the Code as Legacy series, and I’m deciding to stop.
My Biggest Enemy Writes My Code

My Biggest Enemy Writes My Code

Past Self wrote the code I maintain today. He had context I’ve lost, constraints I’ve forgotten, and reasons he never documented. He’s gone now, but the code isn’t. This is the second part of the Code as Legacy series, about the engineer who left me this mess, and what I’m handing Future Self in return.
Six Ways ILogger Silently Fails in Production

Six Ways ILogger Silently Fails in Production

I lost half a day because BeginScope silently did nothing in production: no error, no warning, just a flat stream of undifferentiated log entries. ILogger is a façade over a pipeline full of opt-in behaviour that looks enabled by default. Scopes, structured properties, minimum levels, exception chains, timestamps: all have failure modes that compile cleanly and fail quietly.
The Code You Write Today Is Someone's Problem Tomorrow

The Code You Write Today Is Someone's Problem Tomorrow

The code you create is a valuable legacy — my author bio. Not marketing copy. It’s the most expensive lesson from nearly two decades in production systems. This article explains what it actually means when you’ve lived with the consequences.