tutorial

Monitoring NSQ with Vigilmon

NSQ is a real-time distributed messaging platform designed for high-throughput, fault-tolerant operation. Here's how to monitor nsqd, nsqlookupd, nsqadmin, TCP ports, and topic/channel health with Vigilmon.

NSQ is a modern open-source real-time distributed messaging platform purpose-built for high-throughput, fault-tolerant operation — battle-tested at Bitly, Sprinklr, and across the Go ecosystem. NSQ's decentralized topology means any single node can fail without bringing down the cluster, but that same decentralization means failures can go unnoticed unless you're actively watching. Vigilmon gives you proactive alerting across nsqd health, nsqlookupd discovery, nsqadmin availability, TCP ports, and topic/channel liveness.

What You'll Set Up

  • HTTP monitor for nsqd's /ping health endpoint
  • HTTP monitor for nsqlookupd's /ping health endpoint
  • HTTP monitor for nsqadmin web UI (port 4171)
  • TCP port monitor for nsqd's TCP port (4150)
  • Heartbeat monitor for NSQ topic/channel availability

Prerequisites

  • NSQ 1.2+ running (nsqd + nsqlookupd + nsqadmin)
  • HTTP management ports accessible (nsqd: 4151, nsqlookupd: 4161, nsqadmin: 4171)
  • A free Vigilmon account

Step 1: Monitor the nsqd HTTP Health Endpoint

nsqd exposes an HTTP management API on port 4151. The /ping endpoint returns a literal OK string and HTTP 200 when the daemon is healthy.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter http://your-nsqd-host:4151/ping.
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Optionally set Expected response body contains to OK.
  7. Click Save.

Verify manually:

curl -s http://localhost:4151/ping
# OK

For deeper health checks, nsqd also exposes stats:

curl -s http://localhost:4151/stats | python3 -m json.tool | head -20

If you run multiple nsqd nodes, add one monitor per node — nsqd has no built-in cluster health aggregation endpoint.


Step 2: Monitor the nsqlookupd Health Endpoint

nsqlookupd is the discovery service that producers and consumers use to find which nsqd nodes are hosting specific topics. If nsqlookupd goes down, new connections can't resolve topic locations — existing connections continue but new producers and consumers can't bootstrap.

  1. Click Add MonitorHTTP / HTTPS.
  2. Enter http://your-nsqlookupd-host:4161/ping.
  3. Set Expected HTTP status to 200.
  4. Set Expected response body contains to OK.
  5. Set Check interval to 1 minute.
  6. Click Save.

Verify:

curl -s http://localhost:4161/ping
# OK

Check which nsqd nodes nsqlookupd knows about:

curl -s http://localhost:4161/nodes | python3 -m json.tool
# {
#   "producers": [
#     {"remote_address": "192.168.1.10:4150", "hostname": "nsqd-1", ...}
#   ]
# }

If producers is empty while nsqd nodes are running, they've lost their nsqlookupd registration — a silent failure the /ping monitor alone won't catch. Add a heartbeat (Step 5) to verify end-to-end discovery.


Step 3: Monitor the nsqadmin Web UI

nsqadmin provides the real-time dashboard for topic, channel, and per-node statistics. Its availability also serves as a proxy for the NSQ cluster's ability to serve HTTP management traffic.

  1. Click Add MonitorHTTP / HTTPS.
  2. Enter http://your-nsqadmin-host:4171/.
  3. Set Expected HTTP status to 200.
  4. Set Check interval to 1 minute.
  5. Click Save.

If nsqadmin is deployed behind a reverse proxy (nginx, Caddy), update the URL to the proxied address. The proxy adds TLS — enable Monitor SSL certificate on that monitor and set a 21-day expiry alert (covered in the next step).


Step 4: Monitor the nsqd TCP Port

nsqd listens on TCP port 4150 for producer PUB and consumer SUB connections. A TCP port monitor confirms the data plane is accessible independently of the HTTP management API.

  1. Click Add MonitorTCP Port.
  2. Enter your nsqd host IP and port 4150.
  3. Set Check interval to 1 minute.
  4. Click Save.

NSQ port reference:

| Port | Component | Protocol | |------|-----------|----------| | 4150 | nsqd | TCP (data) | | 4151 | nsqd | HTTP (management) | | 4160 | nsqlookupd | TCP | | 4161 | nsqlookupd | HTTP | | 4171 | nsqadmin | HTTP |

Add TCP monitors for each critical port your applications depend on. If nsqlookupd's TCP port 4160 is unreachable, the lookup protocol itself is broken even if the HTTP /ping still responds.


Step 5: Heartbeat Monitoring for NSQ Topic/Channel Availability

nsqd and nsqlookupd can appear healthy while a specific topic's channel has stalled — a consumer crashed and left messages accumulating without being processed. A heartbeat script publishes a test message and verifies it is consumed, catching this failure mode.

  1. In Vigilmon, click Add MonitorCron Heartbeat.
  2. Set the expected ping interval to 5 minutes.
  3. Copy the heartbeat URL (e.g. https://vigilmon.online/heartbeat/abc123).

Create a Go-based heartbeat script (NSQ's native client ecosystem is Go):

// nsq_heartbeat.go
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/nsqio/go-nsq"
)

const (
	heartbeatURL = "https://vigilmon.online/heartbeat/abc123"
	nsqdAddr     = "localhost:4150"
	topic        = "vigilmon-health"
	channel      = "heartbeat"
)

func main() {
	received := make(chan struct{}, 1)
	var once sync.Once

	cfg := nsq.NewConfig()
	consumer, err := nsq.NewConsumer(topic, channel, cfg)
	if err != nil {
		log.Fatal(err)
	}
	consumer.AddHandler(nsq.HandlerFunc(func(msg *nsq.Message) error {
		once.Do(func() { close(received) })
		return nil
	}))
	if err := consumer.ConnectToNSQD(nsqdAddr); err != nil {
		log.Fatal(err)
	}

	producer, err := nsq.NewProducer(nsqdAddr, cfg)
	if err != nil {
		log.Fatal(err)
	}
	if err := producer.Publish(topic, []byte("ping")); err != nil {
		log.Fatal(err)
	}

	select {
	case <-received:
	case <-time.After(10 * time.Second):
		fmt.Fprintln(os.Stderr, "ERROR: message not consumed within 10s")
		os.Exit(1)
	}

	consumer.Stop()
	producer.Stop()

	resp, err := http.Get(heartbeatURL)
	if err != nil || resp.StatusCode != 200 {
		log.Fatalf("heartbeat ping failed: %v", err)
	}
	fmt.Println("OK: NSQ round-trip verified and heartbeat sent")
}

Build and install:

go mod init nsq_heartbeat
go get github.com/nsqio/go-nsq
go build -o /usr/local/bin/nsq_heartbeat nsq_heartbeat.go

Schedule every 5 minutes:

crontab -e
# Add:
*/5 * * * * /usr/local/bin/nsq_heartbeat >> /var/log/nsq-heartbeat.log 2>&1

If nsqd is down, the publish fails. If the consumer channel is stalled, the message sits unread. Either way, the heartbeat ping is not sent and Vigilmon fires an alert.


Summary

| Monitor | Type | Target | Interval | |---|---|---|---| | nsqd health | HTTP | host:4151/ping | 1 min | | nsqlookupd health | HTTP | host:4161/ping | 1 min | | nsqadmin UI | HTTP | host:4171/ | 1 min | | nsqd TCP port | TCP Port | host:4150 | 1 min | | Topic/channel round-trip | Heartbeat | /heartbeat/abc123 | 5 min |

Five monitors cover the full NSQ stack — discovery, management, data plane, and end-to-end message flow. When any component degrades, Vigilmon alerts you before your consumers start falling behind.


Set up your free Vigilmon account at vigilmon.online and have NSQ monitoring live in under 10 minutes.

Monitor your app with Vigilmon

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

Start free →