SaveApis.Framework

Documentation for SaveApis.Framework

View on GitHub

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:

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/