Nuvora Nexus · .NET 10 · PostgreSQL-native
Every message finds its way.
Nothing gets lost.
Relay is the batteries-included DDD / CQRS / event-sourcing framework for services with real domain behavior — orders, payments, ledgers, bookings. One mediator pipeline in, durable guarantees out.
dotnet add package Nuvora.Nexus.Relay
The shape of a Relay service
Three moves. The pipeline does the rest.
No handler registration, no plumbing copy-paste. Authorization, validation, transactions and the outbox wrap every message automatically — the hundredth command ships as safely as the first.
[RelayHttpPost("/products")]
[RelayHttpTag("Catalog")]
public sealed record CreateProductCommand(
string Name, string Category, decimal Price) : ICommand<Product>;
public sealed class CreateProductCommandHandler(ProductCatalog catalog)
: ICommandHandler<CreateProductCommand, Product>
{
public Task<Product> Handle(
CreateProductCommand command, CancellationToken ct)
{
var product = new Product(
Id: $"p-{Guid.NewGuid():N}",
Name: command.Name.Trim(),
Category: command.Category.Trim().ToLowerInvariant(),
Price: command.Price);
return Task.FromResult(catalog.Save(product));
}
}public sealed record OrderPlaced(
Guid OrderId, string Customer, decimal Total) : DomainEvent
{
public override Guid AggregateId => OrderId;
}
[AggregateType("orders.order")]
public sealed class Order : AggregateRoot<Guid>
{
public static Order Place(Guid id, string customer, decimal total)
{
Guard.AgainstNullOrWhiteSpace(customer, nameof(customer));
Guard.AgainstNegativeOrZero(total, nameof(total));
var order = new Order();
order.RaiseEvent(new OrderPlaced(id, customer.Trim(), total));
return order;
}
// MarkPaid / Ship / Cancel / Refund each RaiseEvent(...)
// State is rebuilt from the event stream — full history, for free.
}var builder = WebApplication.CreateBuilder(args);
// Scans the assembly once: every handler, validator and
// pipeline behavior is discovered and wired automatically.
builder.Services.AddRelay(typeof(CreateProductCommand).Assembly);
var app = builder.Build();
// ProblemDetails + correlation ids around everything downstream.
app.UseRelayExceptionHandling();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// One HTTP endpoint per [RelayHttp*]-annotated message.
endpoints.MapRelayEndpoints();
});
app.Run();Batteries included
The production concerns are the framework.
Mediator & CQRS
One message, one handler, one pipeline. Authorization, validation, logging and transactions wrap every operation uniformly.
Event sourcing
An append-only PostgreSQL event store with snapshots, optimistic concurrency, upcasters and time-travel reads.
Projections
Async read models with checkpoints, lag monitoring, sharded lanes and zero-downtime blue/green rebuilds.
Outbox & inbox
No dual writes, no duplicate side effects: atomic publish on the way out, idempotent consumption on the way in.
Eight broker transports
RabbitMQ, Kafka, Azure Service Bus, Amazon SQS, NATS, Pulsar, ActiveMQ/NMS and in-memory — behind one abstraction.
Sagas & routing slips
Imperative sagas, declarative state machines, and routing slips with LIFO compensation — distributed transactions without 2PC.
Durable scheduling
Delayed commands, recurring cron jobs and redelivery that survive restarts and never run twice across a cluster.
Multi-tenancy
Fail-closed tenant resolution and enforcement, from shared tables with RLS to schema- or database-per-tenant.
Fail-closed authorization
Every message declares its authorization posture — an undecorated command refuses to even start the host.
Query caching
Declarative [Cacheable] queries with stampede protection, backed by memory or Redis.
Observability & resiliency
OpenTelemetry traces and metrics, health checks, retries, circuit breakers, rate and concurrency limits.
Relay Watch
A live control plane: topology, sagas, projections, DLQs, alerts and audit — streamed to a React dashboard.
One abstraction, eight transports
Relay, in stories
Three companies. Thirty ways it goes wrong.
Read with a coffee, not a compiler: three seasons following small teams into the problems every team eventually hits — and how Relay changes the ending.
Season 1
Pemberton & Crumb
A tiny retailer, an improbable success, and a codebase quietly turning to soup.
10 stories →Season 2
Frontrow
A ticketing startup goes viral and learns about scale the hard way.
10 stories →Season 3
Magpie
A money app grows up the careful way — and learns to account for its own past.
10 stories →