ASP.NET Core Health Checks
This page is for operators wiring a Wolverine service into Kubernetes, load-balancer drain logic, or any other system that consumes the standard ASP.NET Core /healthz endpoint.
What this is for
The Wolverine.HealthChecks package plugs Wolverine's runtime state into the ASP.NET Core health-check pipeline. When you enable it, anything that asks your service "are you healthy?" via the standard health endpoint gets a yes/no answer derived from Wolverine's actual state — not just "the web server is up."
The two big consumers of that answer:
- Kubernetes liveness probes. If the probe fails, the pod gets restarted. Use this for "the runtime is in a state we can't recover from, please cycle me."
- Kubernetes readiness probes (and any HTTP load balancer with a similar concept). If the probe fails, the pod stays running but is pulled out of the rotation. Use this for "I'm here but don't send me traffic right now" — startup, drain, or a transient broker outage.
Other common consumers: blue-green deploy gates, canary analysis, and the "is it safe to recycle this node" check that operators run before manual maintenance.
How this differs from CritterWatch's own health view
CritterWatch and the ASP.NET Core health endpoint answer related but distinct questions.
| Question | Where to look |
|---|---|
| Is this pod safe to keep in the rotation right now? | /healthz (Wolverine.HealthChecks) — one bit per node, consumable by k8s and load balancers |
| Why is this service slow? Which listener is jammed? Which projection is lagging? | CritterWatch — per-agent, per-endpoint, per-broker detail for human operators |
The ASP.NET Core health endpoint is for machines making routing decisions. CritterWatch is for humans diagnosing problems.
When the CritterWatch Service Details Overview tab shows the green Registered badge, your service is reporting its Wolverine state to anything that asks via /healthz — that's how Kubernetes decides whether to route traffic to a pod. When it shows the amber Not registered badge, k8s has no signal from Wolverine; the service is either invisible to the orchestrator or relying on a generic "the web server is up" check that won't catch most failure modes.
Wiring it up
Three lines in Program.cs. Add the package reference:
dotnet add package Wolverine.HealthChecksRegister the check and map the endpoint:
builder.Services.AddHealthChecks()
.AddWolverine();
// ...
app.MapHealthChecks("/healthz");Refresh your service's CritterWatch page after the next deploy. The Health checks card on the Overview tab should flip to green Registered, listing the check name (wolverine by default) and any tags you added.
Splitting liveness and readiness
The conventional Kubernetes pattern is two endpoints driven by tags:
builder.Services.AddHealthChecks()
.AddWolverine(tags: new[] { "live", "ready" });
app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("live"),
});
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready"),
});Then in your Kubernetes manifest:
livenessProbe:
httpGet:
path: /healthz/live
port: 8080
readinessProbe:
httpGet:
path: /healthz/ready
port: 8080The CritterWatch Health checks card shows your registered tags as chips so you can confirm the split is in place at a glance.
Listener-level health
The AddWolverineListeners() extension is strictly stronger than AddWolverine(). The bus check tells you "the runtime started"; the listener check tells you "every active listener is still accepting messages." Use it when one stuck listener should pull the pod out of rotation, even though the runtime itself is still alive.
builder.Services.AddHealthChecks()
.AddWolverine(tags: new[] { "live", "ready" })
.AddWolverineListeners(tags: new[] { "ready" });The listener check reports:
Healthy— every listener isAccepting.Degraded— at least one listener isTooBusyorGloballyLatched.Unhealthy— every listener has stopped, or no listeners exist when one is expected.
Tag the listener check with ready only (not live). A jammed listener should bleed traffic away, but it's not necessarily a reason to restart the pod — let the readiness probe recover when the back-pressure clears.
Operator action when CritterWatch shows "Not registered"
The amber Not registered badge means CritterWatch found a service that's wired up to it for monitoring but isn't reporting Wolverine state to ASP.NET Core. Two paths forward:
- You don't need k8s probes for this service — for example, a background worker without an HTTP surface. Acknowledge the warning; nothing is broken.
- You do need probes — follow the wiring snippet above. The card refreshes automatically after the next deploy.
If you've registered the package but still see "Not registered," check that the Wolverine.HealthChecks package version matches your Wolverine runtime version. CritterWatch detects the registrations by full type name, so a stale package reference (typo'd namespace, forked build) won't show up as registered even though /healthz works.
