HiveMQ is the enterprise MQTT broker that keeps industrial sensors, connected vehicles, smart home devices, and telemetry pipelines running. Unlike general-purpose message brokers, HiveMQ is built for massive MQTT client concurrency — hundreds of thousands of persistent sessions, retained message stores that survive restarts, and clustering with zero-downtime rolling upgrades.
But HiveMQ failures hit hard: a node leaving the cluster silently redistributes sessions across remaining nodes, a retained message store that grows without bound eventually slows publishes, and a malfunctioning extension can degrade the entire broker without crashing it. Vigilmon gives you external visibility into HiveMQ health through its built-in REST management API and heartbeat monitors for your MQTT consumer services.
Why HiveMQ Needs External Monitoring
HiveMQ ships with Control Center (the web UI) and exposes metrics via Prometheus. But those require active watching. External monitoring with Vigilmon adds:
- Proactive alerting when node health REST endpoints return errors or nodes leave the cluster
- Client session count monitoring so you know when device connections start dropping
- Message throughput anomaly detection via a health sidecar that tracks publish and subscribe rates
- Retained message store size tracking before it impacts publish latency
- Extension health checks for critical HiveMQ extensions (bridge, enterprise security)
- Heartbeat monitoring for MQTT subscriber applications that must prove they are actively processing
Step 1: Enable the HiveMQ REST Management API
HiveMQ Enterprise exposes a REST API for cluster and broker management. Configure it in config.xml:
<!-- config.xml -->
<rest-api>
<enabled>true</enabled>
<listeners>
<http-listener>
<port>8888</port>
<bind-address>0.0.0.0</bind-address>
</http-listener>
</listeners>
</rest-api>
Restart HiveMQ and verify the API is up:
# Get cluster node list
curl -u admin:admin http://localhost:8888/api/v1/nodes
# Get broker health
curl -u admin:admin http://localhost:8888/api/v1/health
# Get all connected clients count
curl -u admin:admin http://localhost:8888/api/v1/mqtt/clients
For HiveMQ Community Edition, the REST API is not available — use the Prometheus metrics endpoint instead (see Step 3).
Step 2: Build a HiveMQ Health Endpoint
Write a lightweight health sidecar that queries HiveMQ's REST API and surfaces a clean /health endpoint for Vigilmon:
# hivemq_health.py
from flask import Flask, jsonify
import requests, os
app = Flask(__name__)
HIVEMQ_API = os.environ.get('HIVEMQ_API_URL', 'http://localhost:8888/api/v1')
HIVEMQ_USER = os.environ.get('HIVEMQ_API_USER', 'admin')
HIVEMQ_PASS = os.environ.get('HIVEMQ_API_PASS', 'admin')
SESSION_DROP_THRESHOLD = float(os.environ.get('HIVEMQ_SESSION_DROP_THRESHOLD', '0.10'))
RETAINED_MSG_LIMIT = int(os.environ.get('HIVEMQ_RETAINED_MSG_LIMIT', '100000'))
def api_get(path):
r = requests.get(f"{HIVEMQ_API}{path}",
auth=(HIVEMQ_USER, HIVEMQ_PASS), timeout=5)
r.raise_for_status()
return r.json()
@app.route('/health/hivemq')
def health():
issues = []
# Node health
try:
health_data = api_get('/health')
if health_data.get('status') != 'HEALTHY':
issues.append(f"broker_status_{health_data.get('status', 'unknown')}")
except Exception as e:
return jsonify(status='down', reason=str(e)), 503
# Cluster nodes
nodes = api_get('/nodes').get('items', [])
unhealthy_nodes = [n for n in nodes if n.get('status') != 'RUNNING']
if unhealthy_nodes:
issues.append(f"unhealthy_nodes_{len(unhealthy_nodes)}")
if issues:
return jsonify(status='degraded', issues=issues,
total_nodes=len(nodes)), 503
return jsonify(
status='ok',
total_nodes=len(nodes),
healthy_nodes=len(nodes) - len(unhealthy_nodes),
), 200
@app.route('/health/hivemq/sessions')
def sessions():
issues = []
clients = api_get('/mqtt/clients')
total = clients.get('total', 0)
connected = sum(1 for c in clients.get('items', [])
if c.get('connected'))
# Alert if connected fraction drops sharply
if total > 0 and (connected / total) < (1.0 - SESSION_DROP_THRESHOLD):
issues.append(f"connected_clients_{connected}_of_{total}")
if issues:
return jsonify(status='degraded', issues=issues,
total=total, connected=connected), 503
return jsonify(status='ok', total=total, connected=connected), 200
@app.route('/health/hivemq/retained')
def retained():
try:
# HiveMQ EE: retained messages count via REST
retained = api_get('/mqtt/retained-messages')
count = retained.get('total', 0)
if count > RETAINED_MSG_LIMIT:
return jsonify(
status='degraded',
reason='retained_message_store_bloat',
count=count,
limit=RETAINED_MSG_LIMIT,
), 503
return jsonify(status='ok', retained_count=count), 200
except Exception as e:
return jsonify(status='unknown', error=str(e)), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3007)
Step 3: Prometheus Metrics Endpoint
HiveMQ can expose Prometheus metrics via the HiveMQ Prometheus extension (Community and Enterprise):
<!-- hivemq-prometheus-extension/prometheusextension.properties -->
port=9399
bind-address=0.0.0.0
metric-path=/metrics
Verify the metrics endpoint:
curl http://localhost:9399/metrics | grep hivemq_
Key HiveMQ Prometheus metrics to watch:
| Metric | Alert condition |
|---|---|
| hivemq_networking_connections_current | Drops >10% in 5 minutes |
| hivemq_messages_incoming_publish_rate | Falls to 0 unexpectedly |
| hivemq_messages_outgoing_publish_rate | Falls to 0 unexpectedly |
| hivemq_retain_messages_current | Exceeds capacity threshold |
| hivemq_cluster_nodes_count | Drops below expected cluster size |
Build a Prometheus health probe:
@app.route('/health/hivemq/prometheus')
def prometheus_health():
r = requests.get('http://localhost:9399/metrics', timeout=5)
if r.status_code == 200 and 'hivemq_' in r.text:
# Parse connection count from Prometheus text format
for line in r.text.splitlines():
if line.startswith('hivemq_networking_connections_current'):
conn_count = float(line.split()[-1])
return jsonify(status='ok', connections=int(conn_count)), 200
return jsonify(status='ok'), 200
return jsonify(status='down', reason='prometheus_endpoint_unavailable'), 503
Step 4: Extension Health Monitoring
HiveMQ extensions (bridge, enterprise security, Kafka extension) run in-process. A misbehaving extension can degrade the broker without crashing it. Check extension status via the REST API:
@app.route('/health/hivemq/extensions')
def extensions():
try:
ext_list = api_get('/extensions')
unhealthy = [e for e in ext_list.get('items', [])
if e.get('enabled') and e.get('state') != 'STARTED']
if unhealthy:
return jsonify(
status='degraded',
reason='extensions_unhealthy',
extensions=[e['id'] for e in unhealthy],
), 503
return jsonify(
status='ok',
extension_count=len(ext_list.get('items', [])),
), 200
except Exception as e:
return jsonify(status='unknown', error=str(e)), 200
Step 5: Configure Vigilmon HTTP Monitors
- Log in to vigilmon.online and go to Monitors → New Monitor
- Choose HTTP / HTTPS
- Set the URL to your HiveMQ health endpoint:
https://your-app.example.com/health/hivemq - Set the check interval to 1 minute
- Under Expected response, configure:
- Status code:
200 - Response body contains:
"status":"ok" - Response time threshold:
3000ms
- Status code:
- Under Alert channels, assign your Slack or PagerDuty integration
- Save the monitor
Add monitors for granular IoT broker coverage:
| Monitor URL | Purpose | Interval |
|---|---|---|
| /health/hivemq | Node health, cluster node count | 1 min |
| /health/hivemq/sessions | Client connection count and drops | 1 min |
| /health/hivemq/retained | Retained message store growth | 5 min |
| /health/hivemq/extensions | Extension health (bridge, security) | 2 min |
| /health/hivemq/prometheus | Prometheus metrics availability | 5 min |
Step 6: Heartbeat Monitoring for MQTT Consumer Services
In IoT architectures, the HiveMQ broker can be healthy while a backend subscriber service that processes device telemetry silently falls behind or crashes. Vigilmon heartbeat monitors detect this gap.
Set Up the Heartbeat Monitor
- In Vigilmon, go to Monitors → New Monitor → Heartbeat
- Set the name:
hivemq-telemetry-processor - Set the expected interval: 5 minutes
- Set the grace period: 10 minutes
- Save — copy the heartbeat URL:
https://vigilmon.online/heartbeat/abc123xyz
Wire It Into Your MQTT Subscriber (Python — paho-mqtt)
# subscriber.py
import paho.mqtt.client as mqtt
import requests, os, time
VIGILMON_URL = os.environ['VIGILMON_HEARTBEAT_URL']
BROKER_HOST = os.environ['HIVEMQ_HOST']
BROKER_PORT = int(os.environ.get('HIVEMQ_PORT', '8883'))
TOPIC = os.environ['MQTT_TOPIC']
msg_count = 0
last_heartbeat = time.time()
HEARTBEAT_EVERY_N = 200
HEARTBEAT_INTERVAL = 60
def on_message(client, userdata, msg):
global msg_count, last_heartbeat
process_telemetry(msg.payload)
msg_count += 1
now = time.time()
if msg_count % HEARTBEAT_EVERY_N == 0 or now - last_heartbeat > HEARTBEAT_INTERVAL:
try:
requests.get(VIGILMON_URL, timeout=3)
except Exception:
pass
last_heartbeat = now
def on_disconnect(client, userdata, rc):
if rc != 0:
print(f"Unexpected disconnect: {rc}")
# Paho will auto-reconnect with reconnect_delay_set
def process_telemetry(payload):
pass # your processing logic
client = mqtt.Client(client_id="telemetry-processor", clean_session=False)
client.username_pw_set(os.environ['HIVEMQ_USER'], os.environ['HIVEMQ_PASS'])
client.tls_set() # use TLS for port 8883
client.on_message = on_message
client.on_disconnect = on_disconnect
client.reconnect_delay_set(min_delay=1, max_delay=30)
client.connect(BROKER_HOST, BROKER_PORT, keepalive=60)
client.subscribe(TOPIC, qos=1)
client.loop_forever()
Node.js Subscriber (mqtt.js)
// subscriber.js
const mqtt = require('mqtt');
const axios = require('axios');
const client = mqtt.connect(`mqtts://${process.env.HIVEMQ_HOST}:8883`, {
username: process.env.HIVEMQ_USER,
password: process.env.HIVEMQ_PASS,
clientId: 'telemetry-processor',
clean: false, // persistent session
reconnectPeriod: 3000,
});
let msgCount = 0;
let lastHeartbeat = Date.now();
const HEARTBEAT_EVERY_N = 200;
const HEARTBEAT_INTERVAL_MS = 60_000;
client.on('message', (topic, payload) => {
processTelemetry(payload);
msgCount++;
const now = Date.now();
if (msgCount % HEARTBEAT_EVERY_N === 0 || now - lastHeartbeat > HEARTBEAT_INTERVAL_MS) {
axios.get(process.env.VIGILMON_HEARTBEAT_URL).catch(() => {});
lastHeartbeat = now;
}
});
client.subscribe(process.env.MQTT_TOPIC, { qos: 1 });
Step 7: Alert Routing
| Monitor | Alert Channel | Priority |
|---|---|---|
| Node health /health/hivemq | Slack + PagerDuty | P1 |
| Client sessions /health/hivemq/sessions | Slack + PagerDuty | P1 |
| Extensions /health/hivemq/extensions | Slack | P2 |
| Retained store /health/hivemq/retained | Slack | P2 |
| Heartbeat: telemetry processor | Slack + email | P2 |
For IoT deployments, a sudden drop in client connections is usually more urgent than message throughput dips — devices with poor connectivity may reconnect naturally, but a coordinated drop (all devices losing sessions simultaneously) signals a broker-side issue. Configure the sessions monitor with a tight threshold and PagerDuty escalation.
Summary
HiveMQ powers IoT device connectivity at scale, and silent failures hit thousands of devices at once. External monitoring with Vigilmon catches these before device data stops flowing:
| Monitor Type | What It Covers |
|---|---|
| HTTP monitor on /health/hivemq | Broker node health, cluster node count |
| HTTP monitor on /health/hivemq/sessions | Client connection count and session drops |
| HTTP monitor on /health/hivemq/retained | Retained message store growth |
| HTTP monitor on /health/hivemq/extensions | Extension health for bridge and security |
| Heartbeat monitor | Subscriber application liveness |
Get started free at vigilmon.online — your first HiveMQ monitor is running in under two minutes.