CritterStack Utility
SaveApis.Utils.CritterStack integrates Marten (event store + document database) and Wolverine (message bus) into any SaveApis application via the Installer system.
Table of Contents
Overview
Purpose: Provides a fully configured Marten + Wolverine stack with PostgreSQL persistence, event sourcing, multi-tenancy, and OTLP-integrated observability.
When to use: Use this utility when your application needs:
- Event sourcing or CQRS patterns (Marten event store)
- Reliable async messaging between services (Wolverine + PostgreSQL transport)
- PostgreSQL-backed document storage
Compatible with: All SaveApis application types — Web, Console, and CLI.
Installation
Add the CritterStack installers via the AddCritterStack() extension method on the application builder:
await SaveApisApplication
.AsWeb(args, (app, installer) =>
{
app.Name = "My.Service";
app.Namespace = "My.Org";
installer.SetSoftwareAssembly();
})
.AddCritterStack() // registers CritterStackInstaller, MartenInstaller, WolverineInstaller
.Build()
.RunAsync();
AddCritterStack() is a generic extension on ISaveApisApplicationBuilder<TBuilder, TApplication, TContext> — it works the same way on all application types.
Installers
CritterStackInstaller
Key: CritterStack
Configures the shared JasperFx defaults for both Marten and Wolverine:
| Setting | Value |
|---|---|
ApplicationAssembly |
context.SoftwareAssembly |
GeneratedCodeOutputPath |
Generated/CritterStack |
GeneratedCodeMode |
Dynamic (code is generated at runtime) |
ResourceAutoCreate |
All (all required database objects are created automatically) |
This installer must run before MartenInstaller and WolverineInstaller (enforced by AddCritterStack() registration order).
MartenInstaller
Key: Marten
Configures Marten with a PostgreSQL connection, event sourcing, multi-tenancy (Conjoined), and Wolverine integration:
| Feature | Configuration |
|---|---|
| Connection | Built from Marten:* options (see below) |
| Serialization | System.Text.Json with enums as strings |
| Tenancy | TenancyStyle.Conjoined for both documents and events |
| Event store | Identity map for aggregates, archived stream partitioning enabled |
| Projections | Identity map for aggregates |
| Document metadata | CreatedAt and CorrelationId enabled |
| Sessions | Lightweight sessions |
| Wolverine integration | IntegrateWithWolverine() |
| Async daemon | Configurable via Marten:Mode (default: HotCold) |
| OpenTelemetry | Connection-level tracking enabled |
Configuration (section Marten):
| Key | Type | Default | Required | Description |
|---|---|---|---|---|
Marten:Host |
string |
– | Yes | PostgreSQL host |
Marten:Port |
int |
– | Yes | PostgreSQL port |
Marten:Database |
string |
– | Yes | Database name |
Marten:Username |
string |
– | Yes | Database username |
Marten:Password |
string |
– | Yes | Database password |
Marten:Mode |
DaemonMode |
HotCold |
No | Async daemon mode (HotCold, Solo, Disabled) |
Example (appsettings.json):
{
"Marten": {
"Host": "localhost",
"Port": 5432,
"Database": "my_service",
"Username": "postgres",
"Password": "secret",
"Mode": "HotCold"
}
}
Note: In
Development, Npgsql error details and parameter logging are enabled automatically.
WolverineInstaller
Key: Wolverine
Configures Wolverine with PostgreSQL-backed message persistence, structured logging, JSON serialization, and two built-in message queues:
| Feature | Configuration |
|---|---|
| Message storage | Auto-build on startup (AutoCreate.All) |
| Logging | Message start, execution, and success logged at Information |
| Serialization | System.Text.Json with enums as strings |
| Local queue | messages — for ILocaleMessage |
| PostgreSQL queue | messages — for IServiceMessage |
| OpenTelemetry | Metrics (Wolverine) and traces (Wolverine) registered |
Enabling & Disabling
Use WithCritterStack() on the installer context to control the entire stack:
installer.WithCritterStack(false); // disables all three installers
installer.WithCritterStack(true); // re-enables (default when AddCritterStack() is called)
This sets feature flags for CritterStack, Marten, and Wolverine simultaneously.
Message Routing
The CritterStack utility defines two message marker interfaces that control how Wolverine routes messages:
ILocaleMessage
Messages that implement ILocaleMessage are published to the local in-process queue named messages. Use this for messages that should be handled within the same application process.
public record MyLocalEvent(Guid Id) : ILocaleMessage;
IServiceMessage
Messages that implement IServiceMessage are published to the PostgreSQL-backed durable queue named messages. Use this for messages that must be reliably delivered across service boundaries or survive process restarts.
public record MyServiceCommand(Guid Id, string Payload) : IServiceMessage;
Both queues are named messages but use different transports — Wolverine resolves the correct transport based on the message type at publish time.
Configuration Reference
| Section | Key | Type | Default | Required |
|---|---|---|---|---|
Marten |
Host |
string |
– | Yes |
Marten |
Port |
int |
– | Yes |
Marten |
Database |
string |
– | Yes |
Marten |
Username |
string |
– | Yes |
Marten |
Password |
string |
– | Yes |
Marten |
Mode |
DaemonMode |
HotCold |
No |
Installer Sub-Pages
| Installer | Sub-Page |
|---|---|
CritterStackInstaller |
setup/ |
MartenInstaller |
marten/ |
WolverineInstaller |
wolverine/ |