Feature Flags in .NET
Shipping code is one thing. Deciding who sees it, and when, is another. Feature flags let you decouple deployment from release — you push code to production, but the feature stays off until you're rea...
Resilience with Polly in .NET
Distributed systems fail. A downstream API goes slow, a database hiccups, a network packet gets lost. Your code can either pretend that doesn't happen (and get paged at 2am) or handle it gracefully. P...
Global Error Handling in ASP.NET Core
Every ASP.NET Core app will encounter unhandled exceptions. A database goes away, a downstream service times out, someone passes a value your code didn't anticipate. How you handle those exceptions — ...
Validation with FluentValidation
If you've been using data annotations to validate request models — [Required], [MaxLength], [Range] — you've probably hit the wall where they stop being enough. Conditional rules, cross-property valid...
Caching in ASP.NET Core
Caching is one of those things that looks simple on the surface — store a value, read it back later — but there's a surprising amount of nuance once you start applying it to real services. ASP.NET Cor...
HttpClient Factory in .NET
If you've ever written new HttpClient() inside a method call, congratulations — you've probably introduced a socket exhaustion bug. It's one of the most common mistakes in .NET, and it's subtle enough...
Rate Limiting in ASP.NET Core
Every public API is one viral moment away from being hammered into the ground. Rate limiting is the mechanism that stands between your service and the flood — it caps how many requests a client can ma...
Middleware in ASP.NET Core
Every HTTP request that hits an ASP.NET Core application passes through a pipeline before it ever reaches your endpoint. That pipeline is built from middleware — small pieces of code that each get a c...
The Options Pattern in .NET
Configuration is one of those things that looks simple until it isn't. You start by reading a connection string from appsettings.json, and before long you've got a sprawling mix of IConfiguration.GetS...
Minimal APIs in ASP.NET Core
When ASP.NET Core Minimal APIs landed in .NET 6, I'll be honest — I wasn't sure what to make of them. Controllers had worked fine for years. Why change things? Then I used them for a small internal to...
C# 15 Union Types: Discriminated Unions Arrive
C# developers have wanted discriminated unions for years. There are whole libraries built around the gap — OneOf, ErrorOr, LanguageExt — because the language just didn't have a native answer. That cha...
Background Services in ASP.NET Core
Think about a restaurant kitchen. The wait staff handle the incoming orders — they're your request-handling pipeline, busy and visible. But behind the scenes, someone's doing prep work, cleaning equip...
Health Checks in ASP.NET Core
Yesterday we wired up OpenTelemetry to get traces, metrics, and logs flowing. Today we're looking at health checks — a simpler but equally important piece of the production-readiness puzzle. Where OTe...
Getting Started with OpenTelemetry in ASP.NET Core
Yesterday we added structured logging with Serilog and talked about correlation IDs. Today we're going to complete the picture with OpenTelemetry — the open standard that ties traces, metrics, and log...
Structured Logging in .NET with Serilog
Logging is one of those things every app does, but most apps do badly. You end up with files full of sentences like "User 42 placed order 99 for $19.99" — which looks fine until you need to ...