tutorial

Monitoring NATS Server with Vigilmon

NATS is the backbone of cloud-native messaging — but a silent JetStream storage failure or a disconnected cluster peer can cascade into full microservice outages. Here's how to monitor every NATS layer with Vigilmon.

NATS Server is a high-performance messaging backbone used across microservices, IoT fleets, and distributed systems. It's designed to be fast and resilient — but when JetStream persistence fills up, a cluster loses quorum, or the monitoring endpoint goes dark, your entire message-driven architecture can stall silently. Vigilmon gives you external visibility into NATS health endpoints, TLS certificate expiry, cluster connectivity, and JetStream state — catching problems before your services start dropping messages.

What You'll Set Up

  • HTTP monitor for the NATS monitoring endpoint (/healthz, port 8222)
  • Key metric endpoint checks (/varz, /connz, /routez)
  • TCP monitor for the NATS client port (4222)
  • TCP monitor for NATS cluster routing port (6222)
  • TLS certificate expiry alerts
  • JetStream health check via the monitoring API

Prerequisites

  • NATS Server running (default ports: 4222 client, 8222 HTTP monitoring, 6222 cluster)
  • HTTP monitoring enabled in nats-server.conf (http_port: 8222)
  • A free Vigilmon account

Step 1: Enable the NATS HTTP Monitoring Port

NATS ships with a built-in HTTP monitoring interface. Enable it in your server config if not already active:

# nats-server.conf
port: 4222
http_port: 8222

# Optional: bind monitoring to localhost only for security
# http: "127.0.0.1:8222"

Restart NATS after updating the config:

nats-server -c nats-server.conf
# or via systemd
systemctl restart nats-server

Verify the monitoring port is up:

curl -s http://localhost:8222/healthz
# {"status":"ok"}

Step 2: Monitor the /healthz Health Endpoint

The /healthz endpoint is NATS's dedicated health check — it returns {"status":"ok"} when the server is accepting connections normally.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. URL: http://YOUR_NATS_HOST:8222/healthz.
  4. Check interval: 1 minute.
  5. Expected HTTP status: 200.
  6. Expected response body contains: ok.
  7. Click Save.

For JetStream-enabled deployments, append ?js-enabled=true to check JetStream health at the same time:

http://YOUR_NATS_HOST:8222/healthz?js-enabled=true

This returns an error if JetStream is configured but not running — useful for catching JetStream storage failures that don't affect basic NATS connectivity.


Step 3: Monitor the /varz Server Variables Endpoint

The /varz endpoint returns server statistics including connection count, memory usage, and uptime. Monitoring it verifies that the NATS metrics subsystem is healthy:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://YOUR_NATS_HOST:8222/varz.
  3. Check interval: 2 minutes.
  4. Expected HTTP status: 200.
  5. Expected response body contains: server_id.
  6. Click Save.
# Verify manually
curl -s http://YOUR_NATS_HOST:8222/varz | python3 -m json.tool | head -20

A successful response includes server_id, version, uptime, and connections — confirming the monitoring subsystem and core server are both operational.


Step 4: TCP Monitor for the Client Port

The HTTP monitoring port being up doesn't guarantee the NATS client port (4222) is accepting connections. Your services connect on port 4222 — monitor it directly:

  1. Click Add MonitorTCP Port.
  2. Host: YOUR_NATS_HOST.
  3. Port: 4222.
  4. Check interval: 1 minute.
  5. Click Save.

If NATS is configured with TLS on the client port, the TCP check still works — it verifies the port is open and accepting connections regardless of TLS negotiation.


Step 5: Monitor Cluster Route Connectivity

For clustered NATS deployments, each server connects to peers on port 6222. A lost route means messages aren't being replicated across the cluster.

Add a TCP monitor for the cluster port on each NATS node:

  1. Click Add MonitorTCP Port.
  2. Host: YOUR_NATS_NODE_HOST.
  3. Port: 6222.
  4. Check interval: 2 minutes.
  5. Click Save.

Repeat for each cluster node. Also monitor the /routez endpoint for route-level details:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://YOUR_NATS_HOST:8222/routez.
  3. Check interval: 2 minutes.
  4. Expected HTTP status: 200.
  5. Expected response body contains: num_routes.
  6. Click Save.

If the cluster loses a peer, num_routes drops — you can set up an alert webhook that checks the value if you want numeric threshold alerting.


Step 6: TLS Certificate Expiry Alerts

If NATS is configured with TLS for client connections, server-to-server clustering, or leaf node connectivity, certificate expiry causes immediate connection failures for all clients.

Add SSL certificate monitoring for the NATS host:

  1. Open the HTTP monitor for YOUR_NATS_HOST:8222 (or the TLS-secured NATS endpoint).
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

If your NATS client port uses a self-signed or privately-issued certificate, use the TCP port monitor's SSL check option for port 4222:

  1. Open the TCP monitor for port 4222.
  2. Enable Check TLS certificate if available, or add a separate HTTPS monitor for a NATS WebSocket endpoint (port 443 if configured).
# Check certificate expiry manually
echo | openssl s_client -connect YOUR_NATS_HOST:4222 2>/dev/null | \
  openssl x509 -noout -dates

Step 7: JetStream Health Monitoring

JetStream extends NATS with persistence, replay, and consumer state. If the JetStream storage backend runs out of space or the state store becomes corrupted, streams stall silently.

Use the /jsz monitoring endpoint:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://YOUR_NATS_HOST:8222/jsz.
  3. Check interval: 5 minutes.
  4. Expected HTTP status: 200.
  5. Expected response body contains: config.
  6. Click Save.

For a more precise JetStream check, use the healthz JS flag:

curl -s "http://YOUR_NATS_HOST:8222/healthz?js-enabled=true&js-server-only=true"

Add a heartbeat script that checks JetStream store capacity and pings Vigilmon if healthy:

#!/bin/bash
# /usr/local/bin/check_nats_jetstream.sh
RESPONSE=$(curl -s "http://localhost:8222/healthz?js-enabled=true")

if echo "$RESPONSE" | grep -q '"status":"ok"'; then
    curl -s https://vigilmon.online/heartbeat/YOUR_JS_HEARTBEAT_ID
fi

Schedule every 10 minutes:

*/10 * * * * /usr/local/bin/check_nats_jetstream.sh

Step 8: Configure Alert Channels

NATS issues cascade fast — a JetStream stall can queue-saturate services within seconds.

  1. Go to Alert Channels in Vigilmon and add a Slack or PagerDuty integration for your on-call team.
  2. For the /healthz monitor and TCP port 4222, set Consecutive failures before alert to 1 — these are hard failure signals.
  3. For the /routez cluster monitor, set the threshold to 2 — momentary reconnects during rolling restarts are expected.
  4. For JetStream heartbeats, use 1 — a missed heartbeat means storage is likely full or corrupted.

Summary

| Monitor | Target | What It Catches | |---|---|---| | Health endpoint | http://HOST:8222/healthz | NATS server down, JetStream failure | | Server vars | http://HOST:8222/varz | Monitoring subsystem health | | Client port TCP | HOST:4222 | Client connections unavailable | | Cluster port TCP | HOST:6222 | Cluster routing down | | Route connectivity | http://HOST:8222/routez | Lost cluster peer | | TLS certificate | Port 4222 / 8222 SSL | Certificate expiry | | JetStream heartbeat | Heartbeat URL | Stream storage full or corrupted |

NATS is built for high-throughput resilience — Vigilmon gives you the external monitoring layer that catches the failures NATS itself can't self-report, keeping your message-driven architecture observable from the outside.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →