We do not ship MediatR. Here is what we ship instead, and the catch
Why Slicekit builds on Wolverine instead of MediatR-plus-a-bus, the 2024-25 licensing shift that makes it a buying concern, and an honest look at what you give up.
If you have built .NET services in the last decade, the default request-handling stack writes itself: MediatR for in-process dispatch, AutoMapper for the DTO boundary, and MassTransit or NServiceBus when you need a real message bus. It was the boring, safe, everyone-uses-it choice. Then 2024 and 2025 happened, and “boring and safe” stopped being free.
This post is about why Slicekit does not put MediatR at its core, the licensing story that turned that from a taste preference into a procurement question, and an honest account of what you trade away by choosing differently. You are evaluating a template you intend to run for years. The dependencies at its center matter more than almost anything else in it.
The licensing story, and why “free forever” was never a guarantee
In 2024-2025, several pillars of the common .NET stack moved toward commercial licensing under Lucky Penny Software. MediatR and AutoMapper both announced commercial licensing, and MassTransit announced it is going commercial in a future major version. The MediatR discussion thread is worth reading for the reasoning, and this roundup covers all three together.
None of this is a scandal. Maintainers of widely-depended-on libraries deserve to be paid, and a clearly-priced commercial license is a far healthier outcome than burnout and abandonment. But it does change the math for a template. The two libraries that sat at the center of the default stack, plus the bus many teams reached for next, all shifted their terms inside roughly a year. If you had assumed those dependencies were permanently free, that assumption was always doing unpaid work. For something meant to run for years, picking your central abstractions partly on licensing trajectory is not paranoia, it is diligence.
To be clear about scope: depending on the exact terms and your usage, MediatR-with-a-bus may still be a perfectly defensible choice for many teams. We are not claiming it became unusable. We are claiming the risk profile changed, and a template should not quietly inherit that risk on your behalf.
What Wolverine actually is
Slicekit builds on Wolverine, from Jeremy Miller and
the JasperFx team behind Marten. The first thing to understand is that Wolverine is not a MediatR
replacement and a separate bus stitched together. It is both roles in one library: it can invoke a
handler in memory, which is the MediatR use case, and it can publish and consume messages over external
transports like RabbitMQ. Handlers are plain methods discovered by convention, with no required marker
interface to implement. In Slicekit that means dispatching commands and queries through the same
bus.InvokeAsync, for example the command behind the create-API-key endpoint:
var result = await bus.InvokeAsync<Result<CreateApiKeyResult>>(
new CreateApiKeyCommand(userId, name, expiresAtUtc, scopedPermissions));
The real differentiator is not raw speed, and it is worth saying plainly: Wolverine is not “just a faster MediatR.” The point is its built-in durable transactional inbox and outbox. Within a transactional scope, your state changes and your outgoing messages are persisted in the same database transaction. A relay then sends those messages, giving at-least-once delivery. If the process dies between commit and send, the relay picks the messages back up. This is exactly how Slicekit keeps publishing an event and committing a database change from drifting apart.
Aggregate raises
records a fact in the domain
One transaction
state + outbox row commit together
Relay forwards
resumes after a crash
RabbitMQ
integration events
Handlers react
at least once
This is the gap that the MediatR-plus-a-bus pattern exists to fill. MediatR’s in-process notifications are fire-and-forget with no durability, so the moment you need a message to survive a crash you reach for a separate bus and wire the two together. Wolverine collapses both roles into one consistent set of rules. Jeremy Miller’s Wolverine for MediatR users walks through the mapping if you are coming from that world.
One accuracy guardrail worth stating directly: the durable outbox is not database-agnostic. It needs a supported store, currently PostgreSQL, SQL Server, or RavenDB, backed by Marten or EF Core, as the durability guide documents. Slicekit runs on PostgreSQL, so this is a non-issue here, but if you fork Slicekit toward an unsupported database, the outbox is the feature you would lose.
The catch
Honesty is the only thing that makes this recommendation worth anything, so here is what you give up.
Wolverine has a much smaller community than MediatR. When you hit a strange edge case at 2am, there are far fewer Stack Overflow answers, blog posts, and prior victims who already solved your exact problem. With MediatR, almost any question has been asked before. With Wolverine, sometimes the docs and the source are your only friends.
It is also more opinionated and leans on “magic.” Handler discovery, the source-generated dispatch, and the conventions around method signatures are productive once they click, but they are conventions you have to learn rather than explicit wiring you can read top to bottom. Teams that prize the most literal, no-surprises code sometimes find this uncomfortable.
It pulls you toward the JasperFx ecosystem, Marten in particular. That is a coherent and capable stack, but it is a direction, and adopting Wolverine nudges you down it. And the library is younger than the alternatives it replaces, with the smaller track record that implies.
If what your team wants above all is the most boring, most widely-known option, and the current MediatR license terms work for your usage, then MediatR-with-a-bus remains a legitimate choice. We are not telling you it is wrong. We are telling you why we did not build the template on it.
An honest recommendation
For a long-lived template, we weighted three things: durability guarantees you would otherwise have to assemble yourself, a single consistent model for in-process and cross-process messaging, and a dependency whose licensing trajectory we were comfortable betting years on. Wolverine wins on all three. The price is a smaller community, more convention to learn, and a tilt toward one ecosystem. We think that is the right trade for this use case, and we would rather you make it with eyes open than discover the tradeoffs later.
If you want the concrete details of how commands, queries, events, and the outbox flow through Slicekit, read CQRS and domain events. And for the distinction between CQRS the pattern and the dispatcher people keep mistaking for it, see CQRS is not your mediator.