Built for .NET 8.0

A lightweight, fast mediator for your applications.

Pipelink is a modern, performance-focused .NET library that lets you implement the CQRS pattern in your application by routing requests, publishing notifications, and delegating work to handlers and pipeline behaviors.

39 ns avg. send time
280 B allocated per call
MIT open-source license
UserController.cs
public class UserController : ControllerBase
{
    private readonly Pipelink _pipelink;

    public UserController(Pipelink pipelink)
        => _pipelink = pipelink;

    [HttpGet("{id}")]
    public async Task<ActionResult<UserDto>> GetUser(int id)
    {
        var user = await _pipelink.Send(new GetUserQuery(id));
        return Ok(user);
    }
}
CQRS Pattern · Native Streaming · Microsoft DI Compatible · Compression Support
Features

Everything you need for production, right out of the box

Pipelink gives you the essential building blocks to implement a CQRS architecture through a clean, readable API.

Request / Response

Send requests through the mediator and get type-safe responses back from the matching handler.

📣

Notification Pattern

Publish a single event to multiple handlers and keep your business logic loosely coupled.

🧩

Pipeline Behaviors

Layer in cross-cutting concerns like logging, validation, and caching around your requests.

🌊

Stream Requests

Built-in streaming support for efficiently handling large datasets.

🗜️

Compression Support

Built-in compression support to optimize data transfer.

🔌

Dependency Injection

Seamless, natural integration with Microsoft.Extensions.DependencyInjection.

🔍

Assembly Scanning

Your handlers and behaviors are automatically registered via assembly scanning.

Performance

Built to be fast, from the ground up

Measured on .NET 8.0, Release configuration, on an Apple M3 processor using BenchmarkDotNet v0.14.0.

Method Mean Error StdDev Allocated
Pipelink_Send 39.10 ns 0.179 ns 0.340 ns 280 B

* Results may vary depending on hardware and environment.

39 ns

Sub-microsecond mediator dispatch on average

280 B

Minimal memory allocation per request

↓σ

Low standard deviation for consistent, predictable performance

Quick Start

Set up your mediator flow in four steps

Register Pipelink in your project, define your request and response, write your handler, and start using it.

Program.cs
// In Program.cs or Startup.cs
services.AddPipelink(cfg =>
{
    cfg.RegisterServicesFromAssemblyContaining<Startup>();
});
GetUserQuery.cs
// Request
public record GetUserQuery(int UserId) : IRequest<UserDto>;

// Response
public record UserDto(int Id, string Name, string Email);
GetUserQueryHandler.cs
public class GetUserQueryHandler : IRequestHandler<GetUserQuery, UserDto>
{
    public async Task<UserDto> Handle(GetUserQuery request, CancellationToken cancellationToken)
    {
        // Your implementation here
        return new UserDto(request.UserId, "John Doe", "john@example.com");
    }
}
UserController.cs
public class UserController : ControllerBase
{
    private readonly Pipelink _pipelink;

    public UserController(Pipelink pipelink)
        => _pipelink = pipelink;

    [HttpGet("{id}")]
    public async Task<ActionResult<UserDto>> GetUser(int id)
    {
        var user = await _pipelink.Send(new GetUserQuery(id));
        return Ok(user);
    }
}
Advanced Usage

Notifications and pipeline behaviors

Ready for the advanced scenarios you'll need as your application grows.

Notifications

Publish a single event to multiple independent handlers with no dependencies between them.

public record UserCreatedNotification(int UserId, string Email) : INotification;

public class SendWelcomeEmailHandler
    : INotificationHandler<UserCreatedNotification>
{
    public async Task Handle(UserCreatedNotification n, CancellationToken ct)
    {
        // Send a welcome email
    }
}

await _pipelink.Publish(new UserCreatedNotification(userId, email));

Pipeline Behaviors

Wrap cross-cutting concerns like logging around your requests, before and after handling.

public class LoggingBehavior<TRequest, TResponse>
    : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    public async Task<TResponse> Handle(
        TRequest request, CancellationToken ct,
        RequestHandlerDelegate<TResponse> next)
    {
        _logger.LogInformation("Handling {Request}", request.GetType().Name);
        var response = await next();
        _logger.LogInformation("Handled {Request}", request.GetType().Name);
        return response;
    }
}

Why Pipelink?

A focused toolkit built around a few core ideas:

  • A simple, focused, lightweight implementation
  • Modern language features for .NET 8.0
  • Native streaming support
  • A simplified pipeline architecture
  • Modern DI container integration
Install

Add it to your project with a single command

Pipelink is distributed via NuGet and works with any project targeting .NET 8.0.

$ dotnet add package Pipelink