Hexalith.EventStore.ServiceDefaults
3.126.0
dotnet add package Hexalith.EventStore.ServiceDefaults --version 3.126.0
NuGet\Install-Package Hexalith.EventStore.ServiceDefaults -Version 3.126.0
<PackageReference Include="Hexalith.EventStore.ServiceDefaults" Version="3.126.0" />
<PackageVersion Include="Hexalith.EventStore.ServiceDefaults" Version="3.126.0" />
<PackageReference Include="Hexalith.EventStore.ServiceDefaults" />
paket add Hexalith.EventStore.ServiceDefaults --version 3.126.0
#r "nuget: Hexalith.EventStore.ServiceDefaults, 3.126.0"
#:package Hexalith.EventStore.ServiceDefaults@3.126.0
#addin nuget:?package=Hexalith.EventStore.ServiceDefaults&version=3.126.0
#tool nuget:?package=Hexalith.EventStore.ServiceDefaults&version=3.126.0
Hexalith.EventStore — DAPR-native event sourcing server for .NET
If you've spent weeks wiring up an event store, a message broker, multi-tenant isolation, and a read-model refresh story — only to realize you'll do it again for your next project — we built this for you. Hexalith.EventStore is a distributed, CQRS and DDD-ready event sourcing framework that handles command routing, event persistence, snapshots, query execution, and pub/sub delivery so you can focus on domain logic. Built on DAPR for infrastructure portability.
The Programming Model
Your domain logic lives in an aggregate class with typed Handle methods — conceptually a pure function: $(Command, CurrentState?) \rightarrow List<DomainEvent>$. Each Handle method receives a specific command and the current state, then returns a DomainResult carrying success events or rejections.
public sealed class CounterAggregate : EventStoreAggregate<CounterState>
{
public static DomainResult Handle(IncrementCounter command, CounterState? state)
=> DomainResult.Success(new IEventPayload[] { new CounterIncremented() });
public static DomainResult Handle(DecrementCounter command, CounterState? state)
{
if ((state?.Count ?? 0) == 0)
return DomainResult.Rejection(new IRejectionEvent[] { new CounterCannotGoNegative() });
return DomainResult.Success(new IEventPayload[] { new CounterDecremented() });
}
public static DomainResult Handle(ResetCounter command, CounterState? state)
{
if ((state?.Count ?? 0) == 0)
return DomainResult.NoOp();
return DomainResult.Success(new IEventPayload[] { new CounterReset() });
}
}
public sealed class CounterState
{
public int Count { get; private set; }
public void Apply(CounterIncremented e) => Count++;
public void Apply(CounterDecremented e) => Count--;
public void Apply(CounterReset e) => Count = 0;
}
Under the hood,
EventStoreAggregate<TState>implementsIDomainProcessor— you can still use that interface directly for advanced scenarios (see the legacyCounterProcessorexample).
Why Hexalith?
| Feature | Hexalith | Marten | EventStoreDB | Custom |
|---|---|---|---|---|
| Infrastructure portability | Any store/broker, zero-code swap | PostgreSQL only | Dedicated server | You build it |
| Multi-tenant isolation | Built-in: data, topics, access | Manual | Manual | You build it |
| CQRS/ES framework | Complete, infra-agnostic | Complete, PG-coupled | Storage only, BYO framework | You build it |
| Deployment | DAPR sidecar: Docker, K8s, ACA | App library | Server + clients | You build it |
| Database lock-in | None (Redis, PG, Cosmos, etc.) | PostgreSQL | EventStoreDB | Chosen DB |
Note: Hexalith is not the right tool for every scenario. If you need raw event stream performance or already run PostgreSQL everywhere, see the decision aid.
Get Started
Register the event store in two lines — AddEventStore() scans your assembly for aggregate types, no manual registration needed:
builder.Services.AddEventStore(); // Auto-discovers CounterAggregate
// ...
app.UseEventStore(); // Activates domains with convention-derived names
Beyond commands, the platform includes a query pipeline with ETag-based cache validation, projection invalidation hooks, preflight authorization endpoints, and optional SignalR notifications for real-time read-model refresh.
Get started in under 10 minutes — follow the Quickstart Guide.
Prerequisites: .NET SDK, Docker Desktop, DAPR CLI
Run and Debug in the Platform Workspace
EventStore runs and debugs as a module from the Hexalith.Platform workspace, where this repository is the references/Hexalith.EventStore submodule. From the Platform root, with the pinned module tool, Aspire CLI 13.6.1 exactly, Docker, and HEXALITH_DAPR_HOME pointing at an isolated Dapr home (CLI 1.18.0 at tools/dapr, runtime 1.18.2 in .dapr/bin):
dotnet tool restore
dotnet restore apphost.cs
dotnet tool run hexalith-module -- debug --manifest references/Hexalith.EventStore/module/hexalith.module-manifest.v2.json
dotnet tool run hexalith-module -- down --manifest references/Hexalith.EventStore/module/hexalith.module-manifest.v2.json
Initialize the Platform workspace's direct references/Hexalith.Builds, references/Hexalith.EventStore, references/Hexalith.Tenants and references/Hexalith.Memories checkouts without --recursive, with each HEAD matching its staged Platform gitlink. The tool reads all three declaration owners even for EventStore alone. dotnet restore apphost.cs installs the local Aspire orchestration and dashboard packages before the first run; tool restore alone does not. If NuGet uses a custom globalPackagesFolder, set NUGET_PACKAGES to that absolute folder for both restore and debug; otherwise the tool checks ~/.nuget/packages and reports HXR016 if the packages are missing.
debug builds references/Hexalith.EventStore in Debug, starts only the eventstore gateway with its Dapr sidecar, the Dapr control plane and Redis, waits for /ready, and reports the dotnet run launcher process id. Attach your debugger to the launcher's child process (ps --ppid <launcher-pid> -o pid,args). Stay attached until you finish, then stop the run with down. See CONTRIBUTING.md and the Platform README for the full prerequisites.
debug does not print the run id: it is the file name of the run state <runId>.json under ${XDG_DATA_HOME:-$HOME/.local/share}/hexalith-builds/g4-runs/ on Linux. Inspect the state files and select the one whose projectProcessIds contains the launcher id reported by this debug invocation. Confirm its manifestHash matches sha256sum references/Hexalith.EventStore/module/hexalith.module-manifest.v2.json (ignoring hexadecimal letter case), then use its runId. File modification time alone cannot identify your run. When an earlier run used the same manifest, down --manifest refuses with HXR024; add --run-id <runId>. An explicit --run-id is not cross-checked against the manifest, so verify both fields before stopping it.
This repository's own src/Hexalith.EventStore.AppHost serves only this repository's own tests. A run of it is never evidence that EventStore runs in the Platform composition.
Architecture
flowchart TB
Client([Client Application]) -->|REST commands + queries| CommandAPI[Command API Gateway]
Realtime[Realtime UI / Client] <-.->|SignalR change notifications| CommandAPI
CommandAPI -->|Route command| Actor[Aggregate Actor]
Actor -->|Invoke| Domain[Domain Service<br/>IDomainProcessor]
Domain -->|Return events| Actor
Actor -->|Persist| StateStore[(State Store<br/>Redis / PostgreSQL / Cosmos DB)]
Actor -->|Publish| PubSub{{Pub/Sub<br/>RabbitMQ / Kafka / Azure Service Bus}}
PubSub -->|Subscribe| Projections[Event Handlers / Projections]
Projections -->|Projection changed| CommandAPI
subgraph DAPR ["DAPR Sidecar (Infrastructure Abstraction)"]
StateStore
PubSub
end
<details> <summary>Architecture diagram text description</summary>
The system follows a command-event architecture with a built-in read-model refresh path: client applications send commands and queries via REST to the Command API Gateway, which routes commands to Aggregate Actors and queries to projection handlers. Each actor invokes the domain service (your IDomainProcessor implementation) and persists resulting events to a state store. Events are published to a pub/sub system for downstream consumers, and projection changes can be surfaced back to clients through HTTP cache validators and optional SignalR notifications. DAPR provides the infrastructure abstraction layer, allowing you to swap state stores (Redis, PostgreSQL, Cosmos DB) and message brokers (RabbitMQ, Kafka, Azure Service Bus) without changing application code.
</details>
Documentation
Full documentation index: Documentation
Getting Started
- Quickstart Guide — up and running in under 10 minutes
- Prerequisites — required tools and environment setup
Concepts
- Architecture Overview — system topology and design decisions
- Choose the Right Tool — when Hexalith is (and isn't) the right fit
- Event Versioning & Schema Evolution — safely evolving event schemas over time
Guides
- Upgrade Path — migrating between versions
- DAPR FAQ Deep Dive — honest answers about DAPR dependency, risks, and operational costs
- Deployment Guides — Docker Compose, Kubernetes, Azure Container Apps
- Production Deployment Configuration — DAPR component configs, backend swap, secret management
Reference
- Command API Reference — command submission, status, replay, and preflight validation
- Query & Projection API Reference — query execution, ETag caching, projection notifications, and SignalR
- NuGet Packages Guide — package roles, dependencies, and installation guidance
- Native AOT and IL Trimming Posture — current compatibility posture and reflection convention inventory
- Generated API Reference — auto-generated public type documentation
Community
- Product Roadmap — planned features and project direction
- Awesome Event Sourcing — curated ecosystem resources
- GitHub Discussions — questions, ideas, and community support
- Issue Tracker — bug reports and feature requests
Contributing
Contributions are welcome! Please read the Contributing Guide and Code of Conduct before submitting a pull request.
License
This project is licensed under the MIT License.
See the Changelog for release history and notable changes.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- ByteAether.Ulid (>= 1.4.2)
- Hexalith.Commons.UniqueIds (>= 2.30.3)
- Hexalith.EventStore.Contracts (>= 3.126.0)
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 10.0.13)
- Microsoft.Extensions.Http.Resilience (>= 10.11.0)
- Microsoft.Extensions.ServiceDiscovery (>= 10.11.0)
- Microsoft.IdentityModel.Abstractions (>= 8.23.0)
- Microsoft.IdentityModel.JsonWebTokens (>= 8.23.0)
- Microsoft.IdentityModel.Logging (>= 8.23.0)
- Microsoft.IdentityModel.Protocols (>= 8.23.0)
- Microsoft.IdentityModel.Protocols.OpenIdConnect (>= 8.23.0)
- Microsoft.IdentityModel.Tokens (>= 8.23.0)
- OpenTelemetry (>= 1.20.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.20.0)
- OpenTelemetry.Extensions.Hosting (>= 1.20.0)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.20.0)
- OpenTelemetry.Instrumentation.Http (>= 1.20.0)
- OpenTelemetry.Instrumentation.Runtime (>= 1.20.0)
- System.IdentityModel.Tokens.Jwt (>= 8.23.0)
NuGet packages (6)
Showing the top 5 NuGet packages that depend on Hexalith.EventStore.ServiceDefaults:
| Package | Downloads |
|---|---|
|
Hexalith.EventStore.DomainService
Domain-service host SDK for the Hexalith event store. A domain module references this package and writes only its domain code plus a two-line host (AddEventStoreDomainService / UseEventStoreDomainService) — all hosting, DAPR-endpoint, observability, and discovery boilerplate is provided here. |
|
|
Hexalith.EventStore.Gateway
Reusable EventStore HTTP gateway components — MVC controllers, authentication, authorization, validation, middleware, health checks, OpenAPI helpers, and host registration extensions. |
|
|
Hexalith.Tenants.Server
Multi-tenant management service for .NET built on Hexalith.EventStore |
|
|
Hexalith.Tenants.Testing
Multi-tenant management service for .NET built on Hexalith.EventStore |
|
|
Hexalith.Parties.Projections
DAPR-native party management microservice for .NET |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.126.0 | 20 | 10/18/2026 |
| 3.125.1 | 175 | 10/18/2026 |
| 3.125.0 | 36 | 10/18/2026 |
| 3.124.0 | 523 | 10/16/2026 |
| 3.123.0 | 142 | 10/16/2026 |
| 3.122.0 | 158 | 10/14/2026 |
| 3.121.0 | 186 | 10/14/2026 |
| 3.120.0 | 698 | 10/10/2026 |
| 3.119.0 | 294 | 10/9/2026 |
| 3.118.1 | 119 | 10/9/2026 |
| 3.118.0 | 150 | 10/9/2026 |
| 3.117.1 | 634 | 10/8/2026 |
| 3.117.0 | 153 | 10/8/2026 |
| 3.115.0 | 433 | 10/7/2026 |
| 3.114.0 | 150 | 10/5/2026 |
| 3.113.0 | 257 | 10/4/2026 |
| 3.112.0 | 228 | 10/4/2026 |
| 3.110.0 | 935 | 9/29/2026 |
| 3.109.0 | 582 | 9/26/2026 |
| 3.108.1 | 574 | 9/24/2026 |