Skip to Content

When to Choose a Lightweight Mediator

MediatR is the default choice for the mediator pattern in .NET. It is well-documented, widely used, and backed by a long track record. If you are on a team that already uses it, you have good reasons to stay.

MicroMediator is a newer option built with different priorities: lower allocation, explicit lifetime management, and no assembly scanning. It is not a drop-in replacement with a faster badge. It makes different trade-offs.

This post works through those trade-offs with real benchmark data so you can make an informed choice. All benchmarks run on .NET 10.0, Intel Core Ultra 7 165H, BenchmarkDotNet v0.15.8. The benchmark suite is publicly available on GitHub.


Where MicroMediator is faster

Basic dispatch

The clearest difference is at the dispatch level, before any handler logic runs.

MethodMeanAllocated
MicroMediator (Singleton)24.64 ns96 B
MediatR55.86 ns296 B

MicroMediator caches a typed dispatch wrapper per request type after the first call. MediatR resolves handlers through reflection on each request. That difference accounts for both the speed and allocation gap here.

This is also where the benchmark conditions matter most. MicroMediator uses a Singleton handler. MediatR registers handlers as transient by default via assembly scanning. Singleton dispatch removes DI resolution cost entirely. If you register MicroMediator handlers as Scoped or Transient, the gap narrows. The handler lifetimes post covers this in detail.

With a validation pipeline

Adding FluentValidation pipeline behaviour to both:

MethodMeanAllocated
MicroMediator378.0 ns1.65 KB
MediatR824.1 ns4.02 KB

The ratio holds across pipeline overhead. MicroMediator runs the same validation logic in less than half the time with less than half the allocation.

Exception handling

This is the least-discussed difference and one of the more significant ones.

MethodFailure rateMeanAllocated
MicroMediator0%54.20 ns32 B
MediatR0%1,010.19 ns536 B
MicroMediator10%228.87 ns90 B
MediatR10%1,206.12 ns569 B
MicroMediator50%926.77 ns320 B
MediatR50%1,754.17 ns704 B

At zero failure rate, MediatR costs 18x more per operation in this benchmark. The gap narrows as failure rate increases and exception handling overhead dominates both paths, but MicroMediator stays consistently cheaper throughout.

The benchmark measures 1,000 requests per invocation with OperationsPerInvoke set accordingly, so the per-operation figures are accurate.

Cold start

MethodMeanAllocated
MicroMediator397 μs9.5 KB
MediatR868 μs602 KB

MediatR scans assemblies at startup to discover and register handlers. MicroMediator does not. The 63x allocation difference at cold start is a direct consequence. For serverless functions and containerised workloads that spin up under load, this matters.

Large payloads

Dispatch cost stays consistent regardless of payload size. At 1MB payloads across 100 repeated calls:

MethodMeanAllocated
MicroMediator39,298 ns72 B
MediatR43,280 ns12,872 B

The handler logic dominates execution time — both are processing the same bytes. The allocation gap comes entirely from the dispatch mechanism, not the payload itself.


Where MediatR holds its own

Raw throughput

At 10,000 sequential requests, execution time is effectively equal:

MethodMeanAllocated
MicroMediator Sequential445 μs234 KB
MediatR Sequential451 μs2,187 KB

MediatR is within 1% on execution time. The memory gap is 9x, but if your workload is not memory-constrained, the speed difference will not be your bottleneck.

Long-running workloads

Over 10,000 iterations of sustained request processing:

MethodMeanAllocated
MicroMediator2,268 μs234 KB
MediatR2,049 μs2,812 KB

MediatR is 10% faster here. The allocation ratio is 12x in MicroMediator's favour, but MediatR edges ahead on raw time. This is the benchmark that cuts against the simple narrative. At sustained load with handler logic that is not trivial, MediatR's execution speed is competitive.

Streaming

As covered in the streaming post, both libraries stream at essentially identical speed. At 10,000 items:

MethodMeanAllocated
MicroMediator stream5,454 μs40,840 B
MediatR stream5,245 μs40,984 B

MediatR is marginally faster. The streaming performance story is about early exit and memory behaviour, not about which library you use.

Cancellation

Both libraries handle cancellation identically. At 100ms cancellation on a long-running handler:

MethodMean
MicroMediator108,756 μs
MediatR108,815 μs

No meaningful difference.


The real trade-off

The benchmark data points to a consistent pattern rather than a simple winner.

MicroMediator allocates significantly less in almost every scenario. At 10,000 requests the ratio is 9x. At cold start it is 63x. Over 10,000 long-running iterations it is 12x. If your application runs in a memory-constrained environment, generates GC pressure under load, or initialises frequently, those numbers compound.

MediatR matches or beats MicroMediator on raw execution speed in sustained workloads. The long-running benchmark shows MediatR running 10% faster over 10,000 iterations. Streaming is essentially identical. At high volume with non-trivial handler logic, the execution time gap closes.

The dispatch speed advantage at 24ns vs 56ns matters when dispatch is a meaningful fraction of your total request cost. In most real applications it is not. A database call at 1ms dwarfs a 30ns dispatch difference by four orders of magnitude.


When to choose MicroMediator

  • You are in a memory-constrained environment (containers, serverless, edge)
  • Cold start time matters to your workload
  • You want explicit lifetime control and are willing to pay for it with more verbose registration
  • You are starting a new project and have no existing MediatR investment
  • You process high volumes of lightweight requests where allocation compounds

When to stay with MediatR

  • You have an existing codebase already using MediatR
  • Your team knows it well and migration cost outweighs the allocation savings
  • Your workload is sustained and CPU-bound rather than memory-sensitive
  • You need the broader ecosystem: community extensions, documentation, and established patterns

Migration

If you do want to switch, the surface area is small. Both libraries implement the mediator pattern with IRequest<T>, IRequestHandler<T, R>, and pipeline behaviours. The main differences are registration style and the streaming interface.

MediatR:

services.AddMediatR(cfg => 
    cfg.RegisterServicesFromAssemblyContaining<Startup>());

MicroMediator:

services
    .AddMediator()
    .AddSingletonHandler<GetProductByIdQueryHandler>()
    .AddScopedHandler<CreateOrderCommandHandler>();

The explicit registration is more work upfront. It also removes assembly scanning, which is where the cold start cost comes from.

Pipeline behaviours follow the same pattern. Replace IPipelineBehavior<TRequest, TResponse> implementations from MediatR with IPipelineBehavior<TRequest, TResponse> from MicroMediator's abstractions. The interface shape is deliberately similar.


MicroMediator is available on NuGet: TechnicalDogsbody.MicroMediator. The full benchmark suite is on GitHub if you want to run it against your own workload.

Andy Blyth

Andy Blyth, an Optimizely MVP (OMVP) and Technical Architect at MSQ DX with a keen interest in martial arts, occasionally ventures into blogging when memory serves.

optimizely-mvp-technology

SaaS CMS Cert

contentful-certified-professional

Andy Blyth