MQTT broker monitoring tells you whether messages are flowing before your customers tell you they are not. This guide covers the metrics that actually matter, connections, message rates, dropped messages, latency and retained counts, how to turn them into alerts without noise, and how to build a simple end-to-end probe. You will also see how to watch a broker in the ConnectMQ portal.
Why Broker Monitoring Is Different
A web server failure is usually loud: requests fail and error rates spike. MQTT failures are often silent. A subscriber can stay connected but stop receiving because its subscription was lost after a reconnect without a persistent session. Devices can be connected but publishing nothing because a sensor driver hung. A queue for an offline client can grow quietly until limits are hit.
Good monitoring therefore combines three views:
- Broker-side metrics: what the broker sees, such as connections, throughput and drops.
- Client-side metrics: what devices and applications see, such as connect failures and reconnect counts.
- End-to-end probes: a synthetic client that publishes and receives, measuring whether the system works as a whole.
If you are new to the moving parts, start with what an MQTT broker does.
The Metrics That Matter for MQTT Broker Monitoring
| Metric | What it tells you | Typical alert |
|---|---|---|
| Connected clients | Fleet health, outages, connect storms | Sudden drop or spike versus baseline |
| Connection attempts and failures | Credential problems, attacks, limits | Failure rate above normal |
| Messages received per second | Publishing activity | Drop to near zero for a known-busy fleet |
| Messages sent per second | Delivery to subscribers | Divergence from expected fan-out |
| Dropped or rejected messages | Queues full, size or quota limits | Any sustained non-zero rate |
| Inflight and queued messages | Slow or offline consumers | Steady growth |
| End-to-end latency | User-visible delay | Above your target for several minutes |
| Retained message count | Topic hygiene, storage growth | Unexpected growth |
| Subscription count | Leaks in client code | Steady growth without new clients |
| Resource usage (self-hosted) | CPU, memory, file descriptors | Approaching limits |
Connections
The connected-client count is your fleet's heartbeat. Track it as a time series and learn its daily shape. A cliff means an outage, a network problem or an expired certificate. A sawtooth pattern of drops and recoveries usually means clients are being disconnected repeatedly, often by duplicate client IDs or a too-short keepalive on flaky networks.
Message Rates
Received and sent rates show whether data is moving. For a fleet that reports every minute, the received rate should be roughly predictable. Compare sent to received: the ratio reflects fan-out, so a sudden change means subscribers disappeared or appeared.
Dropped and Rejected Messages
Brokers drop or reject messages for concrete reasons: payload too large, quota exceeded, queue full for a slow consumer, or QoS 0 messages to a client that cannot keep up. In MQTT 5, many of these are visible to the client as reason codes, such as 0x97 (Quota exceeded). Log reason codes on the client side; they are often the fastest diagnosis available.
Latency
Latency is what users feel. Measure it end to end: timestamp a message at the publisher and compare on arrival at a subscriber. Track percentiles, not just averages, because a healthy median can hide a long tail. Region matters too; see MQTT broker latency by region.
Retained Messages and Subscriptions
Retained messages and subscriptions should track your topic design. Unbounded growth usually points to a bug, such as dynamic topic names containing timestamps, or clients subscribing again on every reconnect.
Do Not Forget Client-Side Metrics
The broker only sees what reaches it. Devices and backend services should report their own health: how many connection attempts failed and why, how often they reconnected, how many readings sit in the offline buffer, and the reason codes returned on CONNACK, PUBACK and DISCONNECT. Publish a compact health message on a status topic every few minutes, retained so dashboards always show the latest value. When a site goes dark, those last reports often explain why before anyone visits.
Self-Hosted Brokers: Where Metrics Come From
If you run your own broker, metrics come from the broker itself. Mosquitto, for example, publishes statistics on $SYS/ topics such as $SYS/broker/clients/connected and $SYS/broker/messages/received. Clustered brokers usually expose HTTP APIs or metrics endpoints for scraping. You then wire those into your monitoring system, build dashboards and define alerts, and add host metrics like CPU, memory and open file descriptors. The Mosquitto documentation lists the available $SYS topics.
Build an End-to-End Latency Probe
Whatever broker you use, a synthetic probe is the single most valuable check. It connects as a normal client, publishes a timestamped message to a private topic, receives it back, and records round-trip time. This Python probe uses paho-mqtt 2.x and runs against the public MQTT test broker as written; for production, switch to your private broker credentials and port 8883.
import json
import statistics
import time
import uuid
import paho.mqtt.client as mqtt
HOST, PORT = "broker.connectmq.com", 1883
PROBE_ID = uuid.uuid4().hex[:8]
TOPIC = f"connectmq/demo/{PROBE_ID}/probe"
INTERVAL = 5 # seconds between probes
ALERT_MS = 500 # alert threshold for round-trip time
latencies = []
def on_connect(client, userdata, flags, reason_code, properties):
print("Probe connected:", reason_code)
client.subscribe(TOPIC, qos=1)
def on_disconnect(client, userdata, flags, reason_code, properties):
print("Probe disconnected:", reason_code)
def on_message(client, userdata, msg):
sent = json.loads(msg.payload)["t"]
rtt_ms = (time.time() - sent) * 1000
latencies.append(rtt_ms)
flag = " ALERT" if rtt_ms > ALERT_MS else ""
print(f"rtt={rtt_ms:.0f} ms{flag}")
if len(latencies) % 12 == 0:
recent = latencies[-12:]
print(f"last 12: median={statistics.median(recent):.0f} ms max={max(recent):.0f} ms")
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"probe-{PROBE_ID}")
# Production: client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD"); client.tls_set(); PORT = 8883
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.reconnect_delay_set(min_delay=1, max_delay=60)
client.connect(HOST, PORT, keepalive=30)
client.loop_start()
try:
while True:
if client.is_connected():
client.publish(TOPIC, json.dumps({"t": time.time()}), qos=1)
else:
print("ALERT: probe not connected")
time.sleep(INTERVAL)
except KeyboardInterrupt:
client.loop_stop()
client.disconnect()
Run the probe from the networks your devices use, not only from your data center, and forward its alerts to your paging or chat tool.
Turning Metrics into Useful Alerts
Alert fatigue kills monitoring. Some rules of thumb:
- Alert on symptoms, not causes. "Probe failed for three minutes" is actionable; "CPU at 70%" usually is not.
- Use baselines. Compare connection counts with the same hour last week rather than a fixed number.
- Require persistence. Trigger only after a condition lasts several minutes to absorb brief blips.
- Separate warning from paging. Slow growth in queued messages is a ticket; zero messages from a busy fleet is a page.
- Watch the watchers. Alert if the probe itself stops reporting.
Monitoring on ConnectMQ
With a managed MQTT broker, the provider monitors the infrastructure, but you still need visibility into your own traffic. ConnectMQ gives you several tools in the portal:
- Dashboard with an overview of your broker.
- Live topic explorer to watch messages arrive in real time and spot topics that went quiet.
- In-browser MQTT client to publish and subscribe for quick checks without installing anything.
- Devices view that organizes equipment by ISA-95 levels, useful for industrial fleets.
- Threshold alert rules and alerts log, so out-of-range values raise alerts you can review later.
For per-device connection status, the broker publishes connection state on $SYS/broker/connection/{clientId}/state. A backend service can subscribe to the state topic for important clients, such as gateways, and react when one goes offline. Combined with Last Will messages from your devices and the probe above, that covers both broker-level and application-level health. Outside the portal, the ConnectMQ VS Code extension and the Desktop MQTT explorer are handy for inspecting traffic during development.
Get Started with ConnectMQ
Create a free Serverless broker at app.connectmq.com, no credit card required, and watch your first messages in the live topic explorer within minutes. Then pair it with the probe above and the MQTT production checklist before going live. The cloud MQTT broker guide covers the rest of the hosting picture.
Frequently Asked Questions
What is the most important MQTT broker metric?
Connected clients combined with an end-to-end probe. Together they show whether devices are online and whether messages actually flow.
How do I measure MQTT latency?
Publish a message containing a timestamp and compute the difference when a subscriber receives it. Track percentiles over time, and run probes from the networks your devices use.
Why do my connection counts drop and recover in a sawtooth pattern?
Common causes are duplicate client IDs kicking each other off, keepalive intervals too short for the network, or a device-side watchdog restarting clients.
Do I still need monitoring with a managed broker?
Yes. The provider watches its infrastructure, but only you know what your devices should be sending, so monitor your own traffic and add a synthetic probe.



