Installation
Requirements
- .NET 9.0 or later
- Wolverine 6+ — CritterWatch observes the Wolverine runtime, so every monitored service (and the console itself) runs on Wolverine 6 or later
Durability.Mode = Balancedon every monitored service — even when you run a single node (see note below)- A database for the CritterWatch server's own state — pick one of three:
- PostgreSQL 14+ (via Marten) — the
CritterWatchpackage - SQL Server (via Polecat) — the
CritterWatch.SqlServerpackage - SQLite (via Fisher) — the
CritterWatch.Sqlitepackage; no database server required, it writes to a file
- PostgreSQL 14+ (via Marten) — the
- A Wolverine transport, or the broker-less HTTP / gRPC channel, for service-to-CritterWatch communication — see Transport Requirements
Run monitored services in Balanced durability mode
CritterWatch's projection/subscription Pause and Restart actions are leader-owned agent-assignment changes. Under DurabilityMode.Solo there is no leader and no agent distribution, so those commands silently no-op — the projection keeps running. Set opts.Durability.Mode = DurabilityMode.Balanced on every monitored service; a single Balanced node simply elects itself leader and runs every agent locally, so this costs nothing for single-node deployments. Read-only monitoring, Rebuild, and Rewind work in any mode — only Pause/Restart require Balanced.
Three store flavours for the console's own persistence
The CritterWatch server ships in three interchangeable flavours, one per store. They are the same console — same UI, same HTTP API, same AddCritterWatch(connectionString) / UseCritterWatch() bootstrap — differing only in which package you install and which connection string you hand it:
| Package | Store | Database |
|---|---|---|
CritterWatch | Marten | PostgreSQL |
CritterWatch.SqlServer | Polecat | SQL Server |
CritterWatch.Sqlite | Fisher | SQLite — no database server, just a file |
Pick the one that matches infrastructure you already run. The SQLite flavour is the lightest way to try CritterWatch, or to run it somewhere you'd rather not stand up a database server.
This choice is only about where CritterWatch keeps its own bookkeeping. It is independent of what your monitored services use — they can be on Marten, Polecat, EF Core, RavenDB, or no event store at all.
Fits your existing observability stack
CritterWatch complements the tools you already run rather than replacing them. It links out to distributed traces in Jaeger, and fits alongside metrics tooling like Prometheus and Grafana.
How CritterWatch is hosted
CritterWatch runs as a standalone ASP.NET Core application — a dedicated console you host yourself, separate from the services it monitors. A single CritterWatch instance can monitor many Wolverine applications at once: every service that installs the client package and points at the console shows up in the same dashboard.
Because it is a drop-in ASP.NET Core app, you secure it with any authentication scheme ASP.NET Core supports (cookies, OIDC, Microsoft Entra ID, and so on) and deploy it like any other web application.
No SaaS offering yet
CritterWatch is self-hosted today — you run the console inside your own infrastructure. There is no hosted / SaaS offering at this time.
Clustering CritterWatch
For high availability you can run multiple CritterWatch instances behind a load balancer. The only piece that needs cross-instance coordination is SignalR — the real-time channel that pushes live updates to connected browsers. Everything else (the console's own event store, the Wolverine listeners) already coordinates through shared infrastructure.
Give SignalR a backplane and CritterWatch clusters cleanly. Any SignalR-scale-out option works; the common choices are:
- Redis backplane — a Redis instance fans SignalR messages out across CritterWatch nodes.
- Azure SignalR Service — a managed backplane that offloads connection scale to Azure.
The constraint is only SignalR — anything that lets SignalR scale out will let CritterWatch scale out. See Clustering for the full deployment guide.
NuGet Packages
CritterWatch ships as a client package you install in each monitored service, plus one console package per store flavour — you install exactly one of those three:
Wolverine.CritterWatch
Install this in each monitored service — the applications you want CritterWatch to observe.
dotnet add package Wolverine.CritterWatchThis package contains:
CritterWatchObserver— hooks into the Wolverine runtime and publishes telemetry- All inbound command message types (pause listener, replay messages, etc.)
- All outbound event message types (service updates, health reports, etc.)
CritterWatch / CritterWatch.SqlServer / CritterWatch.Sqlite
Install one of these in your CritterWatch server — the dedicated application that runs the monitoring console. Which one you pick is purely a question of which database you want the console to keep its own state in.
# PostgreSQL (Marten)
dotnet add package CritterWatch
# ...or SQL Server (Polecat)
dotnet add package CritterWatch.SqlServer
# ...or SQLite (Fisher) — no database server needed
dotnet add package CritterWatch.SqliteWhichever you choose, the package contains:
- Hosting extensions (
AddCritterWatch,UseCritterWatch) — identical signatures across all three - Event store projections for service state
- Alert system, SignalR hub, HTTP API
- Embedded Vue SPA (served as embedded assembly resources)
All three depend on the shared CritterWatch.Services package, which carries the store-agnostic console logic. NuGet restores it for you; you don't install it directly.
Version Compatibility
| CritterWatch | .NET | Wolverine | JasperFx | Marten | Polecat | Fisher |
|---|---|---|---|---|---|---|
| This repo today (pre-1.0) | 9.0+ | 6.29.0 | 2.52.1 | 9.28.0 | 5.19.0 | 0.9.2 |
Marten, Polecat, and Fisher are the three store flavours — the console is built against one of them, whichever package you installed, so only the column matching your flavour applies to you.
CritterWatch is built on the same JasperFx ecosystem it monitors. Pins are coordinated across JasperFx / Marten / Polecat / Fisher / WolverineFx — mixing versions across the family breaks on shared internal contracts, so the CritterWatch server in this repo at each version targets one coherent JasperFx stack.
The client package monitored services install — Wolverine.CritterWatch — carries no transitive Marten dependency, so monitored services running RavenDB, EF Core, or no event store at all can install CritterWatch monitoring without pulling Marten onto their build closure. The version table above describes what the CritterWatch server is built against; client-side, the only event-store pin that matters is the JasperFx.Events abstractions package, which Marten, Polecat, and Fisher all implement against.
CritterWatch is currently pre-1.0; minor version bumps may carry breaking wire-format or API changes until 1.0 ships. The version table above reflects what's in this repo's Directory.Packages.props today — see Releases for the published version history.
Transport Requirements
CritterWatch communicates with monitored services over a dedicated Wolverine channel. That channel runs in parallel with your application's existing messaging — it does not replace it, and you do not have to adopt Wolverine as your message bus, or convert any existing messaging, just to use CritterWatch. The channel carries only CritterWatch telemetry and control messages, on its own queue.
You can use any Wolverine-supported transport — see the full list in the Wolverine transport docs:
| Transport | Package | Documentation |
|---|---|---|
| RabbitMQ | WolverineFx.RabbitMQ | RabbitMQ transport ↗ |
| Amazon SQS | WolverineFx.AmazonSqs | Amazon SQS transport ↗ |
| Azure Service Bus | WolverineFx.AzureServiceBus | Azure Service Bus transport ↗ |
| SQL Server | WolverineFx.SqlServer | SQL Server transport ↗ |
| HTTP / gRPC (broker-less) | (built-in) | Wolverine HTTP ↗ |
On Amazon SQS, watch for the 1 MiB message-body limit — the CritterWatch wire format applies brotli compression + lazy-fetch on that transport to stay under it.
No message broker? Use HTTP or gRPC
Not every system worth monitoring is message-driven. Plain web services — an ASP.NET Core API that uses Wolverine only for its HTTP endpoints, with no RabbitMQ / SQS / Azure Service Bus anywhere — can still be monitored. CritterWatch's broker-less channels let the console reach the service over HTTP (a /_wolverine/invoke endpoint) or a Wolverine gRPC port, with no messaging infrastructure to stand up.
If you don't run a broker — or don't want to add one just for monitoring — this is the path. See Transport Options for when it fits and how to wire it up.
The CritterWatch server listens on a dedicated queue (conventionally named "critterwatch"). A single CritterWatch instance can communicate through any number of queues, transport types, or even multiple brokers of the same transport at once — say, two separate RabbitMQ clusters plus an SQS-based service, all in one dashboard (see Wolverine's multiple brokers support). The in-tree dev stack does exactly this. Monitored services pick whichever transport they're already using.
Database Setup
CritterWatch stores its own service state as events, in whichever store flavour you installed. The schema is created automatically on first run in all three cases — you only have to provide something for it to connect to.
SQLite (CritterWatch.Sqlite)
Nothing to set up. Point the connection string at a file path and the console creates it:
Data Source=critterwatch.dbSQL Server (CritterWatch.SqlServer)
Create an empty database on a SQL Server instance the console can reach; CritterWatch creates the schema inside it.
CREATE DATABASE critterwatch;PostgreSQL (CritterWatch)
Create an empty database; CritterWatch creates the schema inside it.
-- Create the database (CritterWatch will create the schema)
CREATE DATABASE critterwatch;The recommended docker-compose.yml fragment for the PostgreSQL flavour:
postgres:
image: postgres:16
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: critterwatch
ports:
- "5432:5432"
rabbitmq:
image: rabbitmq:3-management
ports:
- "5672:5672"
- "15672:15672"Next Step
See the Quick Start Guide to connect your first service.
