DEV Community

Cover image for ConduitR: a fast, open-source alternative to MediatR for .NET
Reza
Reza

Posted on

ConduitR: a fast, open-source alternative to MediatR for .NET

ConduitR is a lightweight mediator for .NET that feels instantly familiar to MediatR users. It’s free, open source, and tuned for performance (cached pipelines, low allocations, built-in telemetry). If you’re considering an alternative as MediatR explores commercial options, ConduitR aims to be a drop-in-feeling choice with a smooth migration path.

Why another mediator?

Mediators help you keep controllers thin, nudge you toward CQRS style, and make cross-cutting concerns (logging, validation, retries) composable. MediatR set the bar for ergonomics in .NET. As the ecosystem evolves (and with increased discussion around commercialization/licensing), many teams want a simple, fast, open option that stays free.

ConduitR was built with that in mind:

  • Familiar API: IRequest<T>, IRequestHandler<TReq,TRes>, INotification, IPipelineBehavior<,>.
  • Performance-first: hot path caching for Send/Stream pipelines, minimal allocations, ValueTask.
  • Batteries as add-ons: Validation (FluentValidation), ASP.NET Core helpers, Pre/Post processors, and Polly-based resilience.
  • Observability: an ActivitySource called "ConduitR" so your mediator shows up in OpenTelemetry traces.

What you get (today)

  • ConduitR (core) – mediator + telemetry spans (Mediator.Send, Mediator.Publish, Mediator.Stream).
  • ConduitR.Abstractions – contracts & delegates.
  • ConduitR.DependencyInjectionAddConduit(...) with assembly scanning.
  • Add-ons:

    • ConduitR.Validation.FluentValidation – automatic validation behavior.
    • ConduitR.AspNetCore – ProblemDetails middleware + minimal API helpers.
    • ConduitR.Processing – MediatR-style Pre/Post processors, as behaviors.
    • ConduitR.Resilience.Polly – retry, per-attempt timeout (pessimistic), circuit breaker.

Quick start

// Program.cs
using System.Reflection;
using ConduitR;
using ConduitR.Abstractions;
using ConduitR.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddConduit(cfg =>
{
    cfg.AddHandlersFromAssemblies(Assembly.GetExecutingAssembly());
    cfg.PublishStrategy = PublishStrategy.Parallel; // or Sequential / StopOnFirstException
});

var app = builder.Build();
app.Run();

// Request + handler
public sealed record Ping(string Name) : IRequest<string>;
public sealed class PingHandler : IRequestHandler<Ping, string>
{
    public ValueTask<string> Handle(Ping req, CancellationToken ct) =>
        ValueTask.FromResult($"Hello, {req.Name}!");
}
Enter fullscreen mode Exit fullscreen mode

Notifications:

public sealed record UserRegistered(string Email) : INotification;

public sealed class SendWelcomeEmail : INotificationHandler<UserRegistered> { /* … */ }
public sealed class AuditLog        : INotificationHandler<UserRegistered> { /* … */ }

// Strategy chosen in AddConduit(...):
await mediator.Publish(new UserRegistered("hi@example.com"));
Enter fullscreen mode Exit fullscreen mode

Streaming:

public sealed record Ticks(int Count) : IStreamRequest<string>;
public sealed class TicksHandler : IStreamRequestHandler<Ticks, string>
{
    public async IAsyncEnumerable<string> Handle(Ticks r, [EnumeratorCancellation] CancellationToken ct)
    {
        for (var i = 1; i <= r.Count; i++) { ct.ThrowIfCancellationRequested(); await Task.Delay(100, ct); yield return $"tick-{i}"; }
    }
}
await foreach (var s in mediator.CreateStream(new Ticks(3))) Console.WriteLine(s);
Enter fullscreen mode Exit fullscreen mode

Migration guide (MediatR → ConduitR)

Good news: the shapes are nearly identical.

MediatR ConduitR
IMediator.Send, .Publish same
IRequest<TResponse> same
IRequestHandler<TReq,TRes> same
INotification / INotificationHandler<T> same
IPipelineBehavior<TReq,TRes> same
Pre/Post processors ConduitR.Processing
Resilience ConduitR.Resilience.Polly

DI switch:

// MediatR
// services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

// ConduitR
services.AddConduit(cfg => cfg.AddHandlersFromAssemblies(typeof(Program).Assembly));
Enter fullscreen mode Exit fullscreen mode

Validation:

// MediatR: separate behavior registration
// ConduitR: one line
services.AddConduitValidation(typeof(Program).Assembly);
Enter fullscreen mode Exit fullscreen mode

Planned tooling:

  • Migration helpers: scripted transformations/aliases to cut over projects quickly.
  • Roslyn analyzers: ensure “one handler per request”, flag missing registrations, encourage cancellation & streaming best practices, and offer code fixes.

Performance notes

  • Cached pipelines per (TRequest,TResponse) for Send and CreateStream (no reflection or delegate recomposition on the hot path).
  • Lean publish path with configurable strategy.
  • Built-in Activity spans with lightweight tags/events.

We’re not publishing synthetic numbers here (your app, your hardware), but in real codebases the no-magic, no-alloc approach pays off.

Cross-cutting: validation, resilience, processors

Validation (FluentValidation):

using ConduitR.Validation.FluentValidation;
services.AddConduitValidation(typeof(Program).Assembly);
Enter fullscreen mode Exit fullscreen mode

Resilience (Polly):

using ConduitR.Resilience.Polly;
services.AddConduitResiliencePolly(o =>
{
    o.RetryCount = 3;
    o.Timeout = TimeSpan.FromSeconds(1); // pessimistic timeout
    o.CircuitBreakerEnabled = true;
});
Enter fullscreen mode Exit fullscreen mode

Pre/Post processors:

using ConduitR.Processing;
services.AddConduitProcessing(typeof(Program).Assembly);
Enter fullscreen mode Exit fullscreen mode

Pros & cons

Pros

  • Familiar API → minimal migration friction.
  • Free & open source.
  • Performance-focused (cached pipelines, ValueTask, low allocations).
  • Built-in telemetry for OpenTelemetry.
  • Optional add-ons: validation, ASP.NET Core helpers, processors, resilience.

Cons (honest)

  • Newer ecosystem (fewer blog posts/samples than MediatR today).
  • Analyzer pack and migration tool are on the roadmap (coming soon).
  • If you depend on specific MediatR extensions, you may need to adapt or open an issue.

License & governance

ConduitR is open source and intended to remain free. Contributions are welcome—issues, PRs, and feature proposals help shape the roadmap.

Top comments (0)