A pragmatic .NET framework for building event-sourced, multi-tenant SaaS applications.
Compendium is the framework that powers Nexus, Sassy Solutions' multi-tenant platform engineering product. It distills years of building event-sourced SaaS into a small set of focused packages: DDD primitives, CQRS handlers, an event store, multi-tenancy, and ready-to-use adapters for PostgreSQL, Redis, Zitadel, and more.
- Zero-dependency Core — Pure DDD primitives (
AggregateRoot<TId>,ValueObject,Result<T>,Error) with no external dependencies beyond the .NET BCL. - CQRS + Event Sourcing built-in — Command/query dispatchers, event store interfaces, and a PostgreSQL adapter wired out of the box.
- Sagas, two flavors —
ProcessManager<TState>for DDD-style orchestration sagas andIHandle<TEvent>for event-driven choreography sagas, each clearly named so you don't have to guess which pattern you're using. See docs/sagas.md. - Multi-tenancy native — Tenant context, resolution, and scoping baked into the primitives — not bolted on.
- Result pattern everywhere — No control-flow exceptions. Every fallible operation returns
Result<T>with structuredErrorvalues. - Modular adapters — Pick only what you need: PostgreSQL, Redis, Zitadel, Listmonk, LemonSqueezy, OpenRouter, ASP.NET Core.
- Battle-tested in production — Powers Nexus, a multi-tenant platform engineering product.
Install the packages you need:
dotnet add package Compendium.Core
dotnet add package Compendium.Application
dotnet add package Compendium.Adapters.PostgreSQLDefine an event-sourced aggregate:
using Compendium.Core.Domain.Primitives;
using Compendium.Core.Results;
public sealed class OrderAggregate : AggregateRoot<OrderId>
{
private OrderStatus _status;
private decimal _amount;
private OrderAggregate(OrderId id) : base(id) { }
public static Result<OrderAggregate> Create(CustomerId customerId, decimal amount)
{
if (amount <= 0)
return Result.Failure<OrderAggregate>(
Error.Validation("Order.Amount.Invalid", "Amount must be positive"));
var order = new OrderAggregate(OrderId.New());
order.AddDomainEvent(new OrderCreated(order.Id, customerId, amount));
return Result.Success(order);
}
public void Apply(OrderCreated @event)
{
_status = OrderStatus.Pending;
_amount = @event.Amount;
}
}Wire it up in Program.cs:
using Compendium.Application.CQRS;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register Compendium CQRS dispatchers (command/query handlers are resolved via IServiceProvider).
builder.Services.AddScoped<ICommandDispatcher, CommandDispatcher>();
builder.Services.AddScoped<IQueryDispatcher, QueryDispatcher>();
// Register your command/query handlers, then wire the PostgreSQL event store adapter
// using the options published by Compendium.Adapters.PostgreSQL.
var app = builder.Build();Core (zero deps) → Abstractions → Application → Infrastructure → Adapters
↓
Multitenancy (cross-cutting)
- Core — Domain primitives with no external dependencies.
- Abstractions — Ports (interfaces) for infrastructure concerns: identity, billing, email, AI.
- Application — CQRS orchestration: command/query handlers, dispatchers.
- Infrastructure — Generic infrastructure concerns: projections, outbox, caching.
- Adapters — Concrete integrations with external systems.
- Multitenancy — Tenant resolution and scoping, usable across all layers.
The full documentation site is being built at sassy-solutions.github.io/compendium (DocFX-powered). In the meantime:
- ROADMAP.md — themes, what's next, and what's out of scope
- CONTRIBUTING.md — build, test, conventions
- docs/adr/ — architecture decision records
- Source under
src/and the Nexus consumer code for end-to-end examples
- Nexus — Multi-tenant platform engineering by Sassy Solutions.
Using Compendium in your project? Open a PR to add yourself to this list.
Contributions, issues, and feedback are welcome. See CONTRIBUTING.md for guidelines on code style, commit conventions, and the development loop.
MIT © 2026 Sassy Solutions. See LICENSE for details.