Skip to content

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.

QuestionWhere 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:

bash
dotnet add package Wolverine.HealthChecks

Register the check and map the endpoint:

csharp
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:

csharp
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:

yaml
livenessProbe:
  httpGet:
    path: /healthz/live
    port: 8080
readinessProbe:
  httpGet:
    path: /healthz/ready
    port: 8080

The 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.

csharp
builder.Services.AddHealthChecks()
    .AddWolverine(tags: new[] { "live", "ready" })
    .AddWolverineListeners(tags: new[] { "ready" });

The listener check reports:

  • Healthy — every listener is Accepting.
  • Degraded — at least one listener is TooBusy or GloballyLatched.
  • 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:

  1. You don't need k8s probes for this service — for example, a background worker without an HTTP surface. Acknowledge the warning; nothing is broken.
  2. 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.

Released under the MIT License.