📑 Table of Contents

Why Developers Are Ditching MediatR for Custom CQRS in .NET 10

📅 · 📁 Opinion · 👁 9 views · ⏱️ 6 min read
💡 MediatR's shift to a paid model is pushing .NET teams to build lightweight CQRS implementations from scratch — and many find it surprisingly simple.

For years, MediatR has been the go-to library for implementing the mediator pattern and CQRS (Command Query Responsibility Segregation) in .NET applications. It is clean, well-documented, and widely adopted. But its recent shift to a paid licensing model for commercial use has triggered a wave of reassessment across the .NET ecosystem — and many developers are arriving at the same conclusion: they don't actually need it.

The conversation intensified this week as a widely shared developer post laid out a compelling case for building CQRS from scratch in .NET 10, arguing that the pattern itself is 'not complicated enough to justify an external dependency.'

What MediatR Actually Does Under the Hood

MediatR, created by Jimmy Bogard, provides an in-process messaging mechanism that decouples request handling from request dispatching. At its core, it does three things: it resolves a handler for a given request type, it invokes that handler, and it optionally runs pipeline behaviors (like logging, validation, or caching) around the handler.

That's it. No distributed messaging. No event bus. No service mesh. It is fundamentally a dependency injection convenience layer — and modern .NET already has a remarkably powerful DI container built in.

With .NET 10 now offering improved minimal APIs, enhanced dependency injection capabilities, and better support for source generators, the gap between what MediatR provides and what the framework offers natively has narrowed considerably.

The Licensing Catalyst

MediatR's move to a paid commercial license — while entirely fair for the maintainer — forced many engineering teams to evaluate the cost-benefit equation. For startups and enterprise teams running dozens of microservices, even modest per-project licensing fees add up.

More importantly, the licensing change prompted a deeper architectural question: should a pattern as fundamental as CQRS depend on a third-party package at all?

'MediatR is a great library. I'm not here to trash it,' the developer wrote. 'But the more I looked at what MediatR actually does under the hood, the more I realised: this is not complicated enough to justify an external dependency.'

Building CQRS From Scratch — What It Takes

The custom implementation typically involves just a few components:

Command and Query Interfaces: Simple generic interfaces like ICommand<TResult> and IQuery<TResult> define the contract. These are trivial to write — often fewer than 10 lines of code combined.

Handler Interfaces: Corresponding ICommandHandler<TCommand, TResult> and IQueryHandler<TQuery, TResult> interfaces mirror what MediatR's IRequestHandler provides.

A Dispatcher: A lightweight dispatcher class uses .NET's built-in IServiceProvider to resolve the correct handler at runtime. With .NET 10's DI improvements, this can be done in under 30 lines.

Pipeline Behaviors: This is where MediatR adds the most value — its pipeline behavior system is elegant. But replicating it with middleware-style decorators or simple wrapper classes is straightforward, especially with .NET 10's support for keyed services and improved generic type resolution.

The entire implementation often clocks in at under 200 lines of production code — fully testable, fully customizable, and zero external dependencies.

The Trade-Offs Are Real

Going custom is not without downsides. MediatR offers battle-tested code, community familiarity, and extensive documentation. New team members likely already know it. Its notification (pub/sub) system, while simple, is convenient out of the box.

Maintaining a custom solution means owning that code forever. Bug fixes, edge cases, and onboarding documentation all fall on your team. For smaller teams or projects with rapid developer turnover, the cognitive overhead of a bespoke solution can outweigh the licensing cost.

A Broader Trend in .NET Architecture

This shift reflects a larger movement in the .NET community toward 'right-sizing' dependencies. As the framework itself grows more capable with each release, developers are questioning whether libraries that once filled genuine gaps still earn their place in the dependency tree.

Similar conversations are happening around AutoMapper, FluentValidation, and other staples of the traditional .NET stack. The philosophy is shifting from 'add a NuGet package' to 'is this worth the coupling?'

What This Means Going Forward

.NET 10 makes building lightweight architectural patterns easier than ever. For teams already comfortable with CQRS concepts, rolling a custom implementation is a weekend project that eliminates a dependency, removes a licensing concern, and often results in code that is simpler to debug.

MediatR remains an excellent choice for teams that value convention and community support. But the era of treating it as a default — an automatic inclusion in every new .NET project — appears to be ending. The real winner here is the pattern itself: CQRS has proven so valuable that developers would rather build it from scratch than go without it.