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)