NATS Server Monitoring on macOS: Endpoints, CLI Tools, and a GUI
A service is publishing, a consumer is falling behind, and someone asks "is the NATS server okay?" You are on a Mac; the server is either running locally under your fingers or in a data center you can only reach over the network. Either way the answer comes from the same place: the read-only HTTP monitoring port every NATS server can expose. This guide covers turning it on, the endpoints worth memorizing, the counters that actually tell you something, and the CLI and GUI tools that save you from curl-ing by hand.
Turn On the Monitoring Port
Monitoring ships with the server but starts switched off. Per the official monitoring docs, pass -m 8222 on the command line or set http_port: 8222 in the config:
nats-server -m 8222
If you do not have a server yet, the NATS getting-started guide installs one on macOS with Homebrew (brew install nats-server); the same page's Docker quick start maps both ports, 4222 for clients and 8222 for monitoring. The monitoring port speaks plain HTTP and answers a GET with a JSON snapshot of the server's state at that instant. Nothing streams, nothing is stored: you ask, it answers. That design means any HTTP client on your Mac can query a server anywhere it can reach.
If you would rather not install a server at all to experiment, NATS Explorer runs an embedded one from the GUI, started with a click; more on that below.
The Endpoints That Matter
The docs single out four endpoints you will use most, plus a health probe:
| Endpoint | Answers | Useful parameters |
|---|---|---|
/varz |
The server process: version, uptime, memory, live and lifetime connection counts, in/out message counters, slow consumers | None needed |
/connz |
Connected clients: connection id, account, authenticated user, round-trip time, pending bytes, subscriptions | acc, subs, auth, sort, limit, offset |
/routez |
Cluster routes: remote server name and id, round-trip time, pending data | None needed for a health glance |
/jsz |
JetStream: stream and consumer counts, meta leader, per-stream state | acc, streams, consumers, limit, offset |
/healthz |
A yes/no probe: 200 when healthy, 503 when not, for orchestrators and load balancers | js-enabled-only, stream/consumer checks |
Two habits from the docs are worth adopting immediately. Scope /connz instead of pulling every connection on a busy node, for example /connz?acc=ORDERS&subs=true to see one account's clients and their subscriptions. And never schedule an unscoped /jsz?accounts=true&streams=true&consumers=true: on a node with thousands of consumers it can take long enough that your scraper times out and you get nothing.
The Counters Worth Watching
connections vs total_connections
These two /varz counters look interchangeable and are not. connections is how many clients are connected right now. total_connections is every connection since the process started, and only climbs. A client stuck in a reconnect loop barely moves the first and inflates the second. A widening gap between them, with slow_consumers above zero, is connection flapping, not load.
slow_consumers
When a subscriber cannot keep up, the server buffers for it, and a client that falls too far behind gets marked a slow consumer. On a healthy node the counter sits at 0. Any nonzero value tells you which direction to dig: sort /connz by pending bytes (/connz?sort=pending&limit=10) and the ten most-backlogged clients float to the top.
JetStream consumer lag
/jsz hands you the raw numbers: stream last_seq, and per-consumer delivery state underneath. The difference between what a stream has stored and what a consumer has acknowledged is the lag, the one number that says a service is behind. The JetStream concepts guide covers how streams and consumers relate; Core NATS vs JetStream vs KV covers when persistence applies at all.
CLI Tools on a Mac
Three tools cover the terminal side, and all three install cleanly with Homebrew:
- curl + jq: zero extra installs.
curl -s http://localhost:8222/varz | jq '{live: .connections, lifetime: .total_connections, dropped: .slow_consumers}'is the flapping check in one line. - The nats CLI (
brew install nats-io/nats-tools/nats): beyond pub/sub it has dedicated monitoring, per its README:nats server check streamandnats server check consumerwatch stream and consumer health with Nagios-compatible exit codes and Prometheus textfile output, ready for cron or a monitoring stack. - nats-top: a separate open-source utility described as a top-like tool for monitoring NATS servers. Point it at a server and watch live connection and throughput tables in a terminal.
A GUI for $SYS and JetStream
There is a second, often overlooked feed: NATS servers publish their own telemetry as messages on $SYS subjects. The numbers arrive on the wire like any other message, which means any client can subscribe, and a GUI can render them live. MacTools NATS Explorer does exactly that: subscribe to $SYS.> and the server stats, connection information, and slow-consumer alerts arrive as pretty-printed JSON in the app, next to your pub/sub and JetStream views.
Where it earns its keep over curl is JetStream debugging. When a consumer is not acking, the app lets you open the stream, inspect consumer state, read pending and redelivery counts, fetch the next message, and purge or replay, without assembling a chain of CLI flags. And because it bundles an embedded NATS server, you can reproduce the whole scenario locally: start the server from the app, connect a misbehaving consumer, and watch the counters move. The NATS client for macOS guide compares it against the CLI and other GUIs.
:8222 can read /connz and see your users, subjects, and traffic. Fine on a laptop, dangerous in production. Lock it down with TLS, an allow list, or system-account access, and never expose it to the public internet.
Which Tool, When
| Situation | Reach for |
|---|---|
| One-off "is the server okay?" from a terminal | curl /varz plus jq, or nats server report |
| Automated checks in cron or CI | nats server check stream/consumer |
| Live tables in an SSH session | nats-top |
| Exploring why a consumer lags, or learning $SYS on a local server | A GUI: NATS Explorer with $SYS monitoring and embedded server |
| Production dashboards and alerting | The monitoring endpoints scraped into Prometheus and Grafana, per the official docs' monitoring chapter |
Frequently Asked Questions
How do I monitor a NATS server?
Enable the built-in monitoring port by starting the server with -m 8222 (or http_port: 8222 in config), then query read-only HTTP endpoints: /varz for server state, /connz for connected clients, /routez for cluster routes, /jsz for JetStream, and /healthz for a yes/no health probe. Any HTTP client works, including curl from a Mac.
What port does NATS monitoring use?
The monitoring port is configurable and off by default. 8222 is the conventional choice and what the official docs use in examples. It is separate from the client port 4222, and the Docker quick start maps both: -p 4222:4222 -p 8222:8222.
Is the NATS monitoring port secure?
No, not by default. The NATS docs warn that the monitoring port is unauthenticated: anyone who can reach it can read /connz, which exposes users, subjects, and traffic. That is acceptable on a laptop, but in production the port must be locked down with TLS, an allow list, or system-account access, and never exposed to the public internet.
Is there a GUI for NATS monitoring on macOS?
Yes. MacTools NATS Explorer ($24 one-time) is a native macOS desktop app that subscribes to the server's $SYS.> monitoring subjects and pretty-prints the JSON, with JetStream stream and consumer browsers showing pending and redelivery counts. It also runs an embedded local server, so you can watch a live server's stats without installing anything else.
Watch Your NATS Server From a Native Mac App
MacTools NATS Explorer: $SYS monitoring with pretty-printed JSON, JetStream stream and consumer debugging, pub/sub with payload viewing, and an embedded server for local testing. Native on macOS, $24 one-time.
Explore NATS Explorer →