Faster.EventBus 0.1.3

dotnet add package Faster.EventBus --version 0.1.3
                    
NuGet\Install-Package Faster.EventBus -Version 0.1.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Faster.EventBus" Version="0.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Faster.EventBus" Version="0.1.3" />
                    
Directory.Packages.props
<PackageReference Include="Faster.EventBus" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Faster.EventBus --version 0.1.3
                    
#r "nuget: Faster.EventBus, 0.1.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Faster.EventBus@0.1.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Faster.EventBus&version=0.1.3
                    
Install as a Cake Addin
#tool nuget:?package=Faster.EventBus&version=0.1.3
                    
Install as a Cake Tool

⚡ Faster.EventBus — Ultra-High-Performance In-Process Command & Event Dispatcher

A near-zero-allocation, pipeline-optimized alternative to MediatR designed for real-time .NET systems.

Faster.EventBus dispatches commands and publishes events using compiled pipeline delegates, avoiding reflection, boxing, and runtime allocations.
Built for extremely high throughput, predictable tail latency, and event processing inside a single .NET process.


✨ Key Features

  • ⚡ Fastest .NET mediator-style system
  • 🧠 No reflection or boxing in hot path
  • 🍃 Zero allocation ValueTask<T> pipelines
  • 🧵 Middleware-style pipeline behaviors
  • 📣 Publish/subscribe event fan-out
  • 🏗 Automatically registers all command & event handlers as Singletons
  • 💉 DI integrated
  • 🧪 Benchmark-proven faster than MediatR

📦 Installation

services.AddEventBus();

📌 Define a Command

public record GetUserNameCommand(int UserId) : ICommand<Result<string>>;

🛠 Create a Command Handler

public class GetUserNameCommandHandler :
    ICommandHandler<GetUserNameCommand, Result<string>>
{
    public ValueTask<Result<string>> Handle(GetUserNameCommand command, CancellationToken ct)
    {
        return ValueTask.FromResult(Result<string>.Success($"User-{command.UserId}"));
    }
}

🧩 Automatic Registration (DI)

Calling services.AddEventBus() automatically:

Type Lifetime
ICommandHandler<TCommand,TResponse> Singleton
IEventHandler<TEvent> Singleton
IPipelineBehavior<TCommand,TResponse> Transient
services.AddEventBus(); // Auto-detects DI handlers and behaviors

🚀 Send a Command

var result = await bus.Send(new GetUserNameCommand(42));
Console.WriteLine(result.Value);

🔧 Pipeline Behaviors Example

Logging Behavior

public class LoggingBehavior<TCommand, TResponse> : IPipelineBehavior<TCommand, TResponse>
    where TCommand : ICommand<TResponse>
{
    public async ValueTask<TResponse> Handle(
        TCommand command,
        CommandBehaviorDelegate<TResponse> next,
        CancellationToken ct)
    {
        Console.WriteLine("Before");
        var result = await next();
        Console.WriteLine("After");
        return result;
    }
}

Validation Behavior

public class ValidationBehavior<TCommand, TResponse> : IPipelineBehavior<TCommand, TResponse>
    where TCommand : ICommand<TResponse>
{
    public async ValueTask<TResponse> Handle(
        TCommand command,
        CommandBehaviorDelegate<TResponse> next,
        CancellationToken ct)
    {
        if (command is IValidatable v && !v.IsValid(out var errors))
            throw new ValidationException(errors);

        return await next();
    }
}

Register behaviors

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));

Execution Chain:

Logging → Validation → Handler

📣 Publish / Subscribe Events

public record UserCreatedEvent(int UserId) : IEvent;

public class UserCreatedEventHandler : IEventHandler<UserCreatedEvent>
{
    public ValueTask Handle(UserCreatedEvent evt, CancellationToken ct)
    {
        Console.WriteLine($"User created: {evt.UserId}");
        return ValueTask.CompletedTask;
    }
}

Registration

services.AddSingleton<IEventHandler<UserCreatedEvent>, UserCreatedEventHandler>();

Publish

await bus.Publish(new UserCreatedEvent(10));

🧠 Use Cases (IUseCaseHandler) — Why and How We Use Them

🎯 What is a Use Case?

A Use Case represents a high-level business workflow initiated by external interaction (UI, API, event, scheduler).
It coordinates multiple operations and executes business orchestration, while ICommandHandler<TCommand,TResponse> executes a single atomic action.

UseCases form the public entry boundary for each feature/module in the modular monolith.
Everything inside a module (commands, handlers, domain, repositories) is private and cannot be accessed from other modules.


❓ Why do we need UseCases?

Without UseCases, systems often fall into the anti-pattern where handlers call handlers:

❌ Problems with handler-chaining

Problem Description
Hidden workflow Flow of business rules is scattered and buried inside handlers
Tight coupling Module A ends up depending on internal code in Module B
Hard to test Requires mocking long dependency call chains
Hard to reason about No single place that reveals full business process
Architecture rot Evolves into spaghetti and breaks modular boundaries

✔ Correct approach: orchestrate inside a UseCase

👍 Benefits

Benefit Description
Visible business flow Easily readable orchestration logic
Clean module boundaries Modules communicate only through use cases
Atomic handlers Each handler does one thing only
Easy testing No deep mock chain dependencies
Replaceable internals Modules can refactor commands without breaking consumers

📦 The IUseCaseHandler Interface

UseCases do not support pipeline behaviors or middleware.
They are intentionally lean, explicit, and synchronous.

public interface IUseCaseHandler<TRequest, TResponse>
{
    ValueTask<TResponse> Handle(TRequest request, CancellationToken ct = default);
}

Example UseCase

public sealed class CheckoutUseCase :
    IUseCaseHandler<CheckoutRequest, Result>
{
    private readonly ICommandDispatcher _dispatcher;

    public CheckoutUseCase(ICommandDispatcher dispatcher)
        => _dispatcher = dispatcher;

    public async ValueTask<Result> Handle(CheckoutRequest request, CancellationToken ct)
    {
        var placed = await _dispatcher.Send(new PlaceOrderCommand(request.OrderId), ct);
        if (placed.IsFailure) return placed;

        var paid = await _dispatcher.Send(new ChargePaymentCommand(request.OrderId), ct);
        if (paid.IsFailure) return paid;

        return await _dispatcher.Send(new ShipOrderCommand(request.OrderId), ct);
    }
}

🧠 Why Event Handlers Must Be Singletons

  • Prevent duplicate fan-out
  • Avoid re-subscription cost
  • Avoid allocation spikes
  • Maintain subscription lifetime consistency

✔ Correct lifetime:

services.AddSingleton<IEventHandler<UserCreatedEvent>, UserCreatedEventHandler>();

🥇 Benchmark Results vs MediatR

Method Calls Mean (ns) Ratio Alloc Alloc Ratio
Faster.EventBus 1 68.37 1.00x 128 B 1.00x
Mediatr 1 127.56 1.87x 504 B 3.94x
Faster.EventBus 100 6,190 1.00x 12 KB 1.00x
Mediatr 100 11,584 1.87 50 KB 3.94x

🔥 ~2× faster & ~4× less memory than MediatR


❤️ Summary

Fast. Lightweight. Production-ready.
If performance matters — use Faster.EventBus.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.3 227 11/23/2025
0.1.2 200 11/22/2025
0.1.1 219 11/22/2025
0.1.0 225 11/22/2025
0.0.4 354 11/21/2025
0.0.3 415 11/19/2025
0.0.2 422 11/18/2025
0.0.1 414 11/18/2025