Skip to main content
The Pragmatic Guide to Adopting .NET 9 in Production — Anselm Fowel
AI & Technology

The Pragmatic Guide to Adopting .NET 9 in Production

4 min read
487 views
Share:

A new major .NET release arrives, and the team chat immediately splits into two camps: the people who want to upgrade this week because it is new, and the people who want to wait two years because change is scary. Both instincts are wrong as stated. Having moved production payment systems across several .NET versions, sometimes smoothly and once memorably not, I have settled into a pragmatic middle path that avoids both reckless early adoption and the slow rot of falling too far behind.

For the service that moves money, boring and well-supported wins.
For the service that moves money, boring and well-supported wins.

Upgrade for reasons, not for novelty

"It is the latest version" is not, by itself, a reason to upgrade a production system that moves people's money. Novelty is not a business case. The reasons that genuinely justify the effort and the risk are concrete and specific.

  • Performance gains that actually move your real bottleneck, not a benchmark you do not care about.
  • Security fixes and a supported lifecycle you cannot responsibly ignore.
  • Features that remove genuine, daily friction your team currently fights.
  • Staying close enough to current that the eventual, unavoidable jump is not enormous.

That last reason quietly matters the most. The teams in real trouble are the ones several major versions behind, facing a migration so large and so risky that no one wants to be the person who starts it, so no one ever does.

Mind the LTS rhythm

Microsoft alternates long-term-support releases with standard-term ones, and that rhythm should shape your strategy directly. For the core systems that underpin a payments business, I weight LTS releases heavily, because the longer support window is worth considerably more to me than the newest features. Stability and a long patch horizon are features, in this context, and arguably the most important ones.

For the service that actually moves money, boring and well-supported beats new and exciting every single time, without exception.

I will happily adopt a standard-term release in less critical, lower-blast-radius services to stay current and let the team learn the new capabilities. But the load-bearing systems track LTS, deliberately and unapologetically.

Upgrade in layers, not in one leap

I never upgrade everything at once, because the runtime, the framework, and the third-party dependencies each carry their own independent risk, and a big-bang upgrade makes it impossible to tell which of them broke the thing that is now broken. When five things changed simultaneously, debugging the regression is a nightmare of elimination.

Enjoying this article?

Get more like it in your inbox — practical engineering leadership, fintech, and AI. No spam, unsubscribe anytime.

Move in layers instead, with a strong test suite catching regressions at each discrete step. Done this way, the upgrade becomes a series of small, individually reversible moves rather than one large, terrifying, all-or-nothing leap. If something breaks, you know exactly which layer did it, because it is the only thing you just changed.

Test the things unit tests miss

Runtime upgrades can shift behavior in subtle ways that unit tests will never catch: serialization edge cases, datetime and timezone handling, garbage-collection and performance characteristics under real load. These are exactly the surprises that pass every test in CI and then bite you in production at peak.

So before a production cutover I run the new version against production-like traffic, ideally a shadow or replay of real load, and watch the metrics that actually matter for the business. The genuinely dangerous surprises almost always live in the gap between "it compiles and the tests are green" and "it behaves identically at production scale."

Have a tested way back

However thorough the testing and however confident the team, I never deploy a runtime upgrade without a tested, rehearsed rollback path. Confidence is an emotion, not a deployment strategy, and the new release will eventually surprise everyone, including the people who built it.

The ability to revert quickly and cleanly is precisely what lets you upgrade boldly, because it bounds the cost of being wrong. A reversible mistake is a learning experience; an irreversible one in a payment system is an incident report and a very long night. That asymmetry is why the rollback plan is not optional.

Anselm Fowel, CTO and fintech architect
Anselm Fowel — CTO & fintech architect

Conclusion: current, deliberately

The goal is to stay current deliberately rather than either chasing every release or hiding from all of them. Upgrade when there is a real reason, weight LTS for the systems that matter, move in reversible layers, test the things that do not show up in unit tests, and always keep a tested way back. Do that consistently and staying on a modern, supported .NET becomes a sustainable, almost boring habit, rather than the terrifying once-every-three-years migration that the teams who avoided it eventually cannot avoid any longer.

Enjoyed this article? Share it with others!

Share:

Get new posts in your inbox

Occasional, practical notes on engineering leadership, fintech, and building with AI. No spam, unsubscribe anytime.

Comments (2)

Leave a Comment

Comments are moderated and will appear after review.

Ama Nkrumah

July 19, 2026

Good writeup. A small nit on "Mind the LTS rhythm": in Postgres you get most of this for free via the primary index.

Kevin Garcia

June 23, 2026

Good topic. EM for 6 years, was IC for 6 before that here. What we do differently: run a shadow processor comparing against production for a week before cut-over on Lattice. It is not universally better; operational complexity is real, but the recovery story is dramatically better and that pays for itself the first time you have to answer a CBN question at 3am.

About the author

Anselm Fowel

Anselm Fowel

Chief Technology Officer & fintech architect. 16+ years leading engineering across AlliancePay, Mondu, Transalliance, Global Accelerex, and Fidelity Bank — writing here about engineering leadership, fintech architecture, and AI in production.

Read next

Subscribe to the newsletter

Practical notes on engineering leadership, fintech, and building with AI — delivered to your inbox. No spam, unsubscribe anytime.

Anselm Fowel

Chief Technology Officer | Fintech Architect | Engineering Leader

Building the future of financial technology through innovative engineering and strategic leadership.

Expertise

  • CTO Advisory
  • Fintech Architecture
  • Team Leadership
  • Technical Strategy
  • System Design

Get In Touch

[email protected]
Lagos, Nigeria

© 2026 Anselm Fowel. Crafted with passion.