Start Debugging
2026-01-08 dotnetdotnet-10

SwitchMediator v3: A Zero-Alloc Mediator That Stays Friendly to AOT

SwitchMediator v3 targets zero-allocation, AOT-friendly dispatch for .NET 9 and .NET 10 CQRS services. Here is what that means and how to benchmark your own mediator.

If you have ever profiled a “clean” CQRS codebase and found death by a thousand allocations in the mediator layer, today’s SwitchMediator v3 release is worth a look. The author is explicitly calling out zero-allocation and AOT-friendly behavior, which is exactly the combination you want in .NET 9 and .NET 10 services that care about latency.

Where typical mediator implementations leak allocations

There are a few common patterns that quietly allocate:

An AOT-friendly mediator usually does the opposite: it makes handler registration explicit and keeps dispatch logic based on known generic types, not runtime reflection.

A small “before vs after” benchmark harness

Even if you do not adopt SwitchMediator, you should benchmark your mediator boundary. This is a minimal harness you can drop into a console app targeting .NET 10 to understand your baseline.

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

public static class Program
{
    public static void Main() => BenchmarkRunner.Run<MediatorBench>();
}

public sealed record Ping(int Value);
public sealed record Pong(int Value);

public interface IMediator
{
    ValueTask<Pong> Send(Ping request, CancellationToken ct = default);
}

public sealed class MediatorBench
{
    private readonly IMediator _mediator = /* wire your mediator here */;

    [Benchmark]
    public async ValueTask<Pong> SendPing() => await _mediator.Send(new Ping(123));
}

What I look for:

If you see allocations in the dispatch path, you can usually find them by switching the return type to ValueTask (as above) and by keeping request/response types as records or structs that are predictable to the JIT.

AOT-friendly usually means “explicit”

If you are experimenting with native AOT in .NET 10, reflection-heavy mediators are one of the first things that break.

The architecture tradeoff is simple:

SwitchMediator’s pitch suggests it is leaning toward the explicit end of the spectrum. That aligns with how I approach performance work: I will take a few more lines of wiring if it buys predictable behavior in production.

If you want the details, start from the announcement thread and follow the repository link from there: https://www.reddit.com/r/dotnet/comments/1q6yl0n/switchmediator_v3_is_out_now_a_zeroalloc/

< Back