composable .net building blocks for microservices
Koto
Koto is a set of small, focused NuGet packages that wire together Wolverine, Marten, FastEndpoints, and EF Core with opinionated conventions for DDD, CQRS, and Event Sourcing. Use what you need, leave the rest.
dotnet add package Koto.Domainbrowse the packages →what it looks like ↓
why
DDD in .NET usually means boilerplate or a licensing trap
Either you write always-valid domain objects, Result-based error handling, and outbox-based event delivery from scratch in every service — or you reach for a framework and later discover it went commercial (MediatR v13+, MassTransit v9+, FluentAssertions v8+).
Koto is a thin, opinionated layer over free, best-in-class .NET libraries — Wolverine for messaging, Marten for event sourcing, FastEndpoints for HTTP, EF Core for persistence — so you get the conventions without the boilerplate or the trap.
what it looks like
A domain model that can't be created in an invalid state
Validation lives in the factory method, not scattered across the codebase. Failures are values — Result<T> — not exceptions.
value object
public sealed class Email : ValueObject
{
public string Value { get; }
private Email(string value) => Value = value;
public static Result<Email> Create(string value) =>
string.IsNullOrWhiteSpace(value) ? Errors.General.ValueIsRequired() :
value.Length > 150 ? Errors.General.InvalidLength(1, 150) :
new Email(value);
}aggregate root
public class Order : AggregateRoot<OrderId>
{
public static Result<Order> Place(Customer customer, IReadOnlyList<OrderItem> items)
{
if (items.Count == 0)
return OrderErrors.NoItems();
var order = new Order(OrderId.New(), customer.Id);
order.AddDomainEvent(new OrderPlacedDomainEvent(order.Id, customer.Id));
return order;
}
public Result<Unit> Cancel(string reason)
{
if (Status == OrderStatus.Cancelled)
return OrderErrors.AlreadyCancelled();
Status = OrderStatus.Cancelled;
AddDomainEvent(new OrderCancelledDomainEvent(Id, reason));
return Unit.Value;
}
}how it fits together
Four principles instead of a framework
01
Always-valid domain
Domain objects cannot be constructed in an invalid state. Validation lives in factory methods, not in validators.
02
Explicit errors, end to end
No exceptions for expected failures. Result<T> flows from the domain all the way to the HTTP response.
03
Events flow to Kafka automatically
Domain events land in the outbox in the same transaction as your write. Wolverine delivers them, in-process handlers publish integration events, Kafka carries them to other services.
04
No magic
No runtime reflection on hot paths. No hidden conventions that surprise you at 2am. The code you write is the code that runs.
domain event → Kafka, automatically
Order.Cancel()
→ AddDomainEvent(OrderCancelledDomainEvent)
→ DbContext.SaveChangesAsync() // outbox, same transaction
→ Wolverine delivers to in-process handler
→ handler publishes OrderCancelledIntegrationEvent
→ Kafka → other servicespackages
Twelve packages. Use what you need, leave the rest.
Koto.Domain
DDD building blocks for .NET microservices. Zero external dependencies.
Koto.Application
CQRS dispatcher, pipeline behaviors, and cross-service integration abstractions.
Koto.Validation
FluentValidation extensions and a CQRS pipeline behavior.
Koto.Infrastructure.EFCore
EF Core 10 integration: generic repository, strongly-typed IDs, specifications, Wolverine outbox.
Koto.Infrastructure.Http
Anti-Corruption Layer for synchronous HTTP calls between services.
Koto.EventSourcing.Marten
Event Sourcing on PostgreSQL via Marten.
Koto.Messaging.Wolverine
Wolverine + Kafka implementation of Koto messaging abstractions.
Koto.Api.AspNetCore
Transport-agnostic ASP.NET Core integration — Minimal APIs, MVC, or any host.
Koto.Api.FastEndpoints
FastEndpoints integration for Koto DDD building blocks.
Koto.Observability
One-liner observability setup: Serilog + OpenTelemetry.
Koto.Scheduling
Quartz.NET-based scheduled jobs and batch processing.
Koto.Testing
DDD-specific test helpers: Given/When/Then for aggregates.
getting started
Add the packages you need
dotnet add package Koto.Domain
dotnet add package Koto.Application
dotnet add package Koto.Infrastructure.EFCoremit licensed · published on nuget
Built for a real production system, open-sourced for everyone else
Koto grew out of building a real .NET microservices backend and was extracted into its own repository once the abstractions earned their keep.