This MQTT production checklist collects the checks that separate a demo that works on your desk from a fleet that runs for years. Work through it before launch to cover TLS, credentials, client IDs, reconnect behavior, topic design, sessions, monitoring and alerting. Each item is short and testable, and the code at the end shows a production-ready client you can adapt for a ConnectMQ broker.
How to Use This Checklist
Treat every item as a yes or no question, and attach evidence: a config file, a test result, a screenshot. Items you deliberately skip should be written down with a reason. Run the list once during development, again before launch, and again after every major firmware or backend change.
If you are still prototyping, the free public MQTT broker is fine for learning, but nothing in this list should be checked against it. Production means a private broker with your own credentials.
Section 1: Broker and Security
- Private broker in place. Production traffic runs on a private broker, not a public test broker.
- TLS only. Devices use port 8883 (MQTT over TLS), browsers use 8084 (Secure WebSocket at
/mqtt). Plain 1883 and 8083 are not used in production firmware. - Certificate validation enabled. Clients verify the broker certificate against a trusted CA. No
insecureflags left over from testing. - CA bundle strategy decided. Devices have a way to receive updated root certificates before the current ones expire.
- Unique credentials. Each device or gateway has its own credentials, so one can be revoked without affecting others.
- No secrets in source control. Credentials live in secure storage or provisioning systems, not in Git or app bundles.
- Revocation tested. You have actually revoked a credential in staging and confirmed the device is refused.
See MQTT security best practices for the reasoning behind these items.
Section 2: Client Identity and Sessions
- Unique, stable client IDs. Each client ID is derived from a serial number or provisioning record and never changes across reboots.
- No duplicate client IDs. Two processes never share an ID; duplicates kick each other off in an endless loop.
- Clean start vs persistent session chosen per client. Subscribers that must not miss messages use persistent sessions; short-lived tools use clean sessions.
- Session expiry set deliberately. In MQTT 5, a session expiry interval matches how long a device may be offline.
- Last Will configured. Devices set a Last Will on a status topic so the backend learns about unexpected disconnects.
Section 3: Connectivity and Reconnects
- Automatic reconnect. Clients reconnect on their own after network loss or broker restarts.
- Exponential backoff with jitter. Retry delays grow and are randomized, so a fleet does not reconnect in lockstep.
- Resubscribe on reconnect. If not using persistent sessions, subscriptions are restored in the connect callback.
- Keepalive tuned. Typical values are 30 to 120 seconds; shorter on stable networks, longer on cellular to save data.
- Offline buffering. Devices buffer readings locally while disconnected, with a cap to protect memory.
- Failure tested. You have pulled the network cable, restarted the broker connection and power-cycled devices, and recovery worked.
Section 4: Topics, Payloads and QoS
- Topic tree documented. A written convention covers levels, naming and examples. Start from the levels your backend needs to route on, such as site, line and device.
- No wildcards in publishing code. Only subscribers use
+and#. - Payload format versioned. JSON or binary payloads include a version field so you can change the schema later.
- Payload size within limits. Messages fit your plan's maximum message size, with headroom.
- QoS chosen per message type. QoS 0 for high-frequency telemetry where a loss is acceptable, QoS 1 for events and commands. See MQTT QoS levels explained.
- Retained messages used intentionally. Retain status and configuration, not every telemetry reading.
Section 5: Capacity and Limits
- Connection count fits the plan. Peak concurrent connections, including backends, tools and staging, stay within plan limits with headroom.
- Message rate estimated. You know your expected messages per second and have tested at a multiple of it.
- Quota handling in clients. MQTT 5 reason codes such as
0x97(Quota exceeded) are logged and cause backoff instead of tight retry loops.
Section 6: Monitoring, Alerting and Operations
- Monitoring live. Connected clients, message flow and an end-to-end probe are monitored. See MQTT broker monitoring.
- Alerts routed. Alerts reach a person, with an on-call owner and a runbook for broker unreachable, mass disconnects and quota errors.
- Staging environment. A separate broker exists for testing firmware and backend changes before they reach the fleet.
Summary Table
| Area | Must-have before launch | Common pitfall |
|---|---|---|
| Security | TLS, unique credentials, revocation | Test credentials shipped in firmware |
| Identity | Stable unique client IDs | Random IDs on every boot |
| Connectivity | Backoff with jitter, offline buffer | Reconnect storms after outages |
| Topics | Documented tree, versioned payloads | Personal data in topic names |
| Capacity | Headroom on connections and size | Forgetting backend and tool connections |
| Operations | Probe, alerts, runbook, staging | Alerts nobody receives |
A Production-Ready Client Template
This Python client, using paho-mqtt 2.x, implements many of the items above: TLS with certificate validation, a stable client ID, a Last Will, MQTT 5 session expiry, resubscription on connect, backoff, and reason-code logging. Replace the placeholders with credentials from the ConnectMQ portal.
import json
import ssl
import time
import paho.mqtt.client as mqtt
from paho.mqtt.packettypes import PacketTypes
from paho.mqtt.properties import Properties
HOST = "YOUR_BROKER_HOST"
CLIENT_ID = "YOUR_CLIENT_ID" # stable, unique per device
BASE = f"plant1/line1/{CLIENT_ID}"
STATUS = f"{BASE}/status"
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print("Connect failed:", reason_code)
return
print("Connected, session present:", flags.session_present)
client.publish(STATUS, "online", qos=1, retain=True)
client.subscribe(f"{BASE}/cmd", qos=1)
def on_disconnect(client, userdata, flags, reason_code, properties):
print("Disconnected:", reason_code) # e.g. Quota exceeded
def on_message(client, userdata, msg):
print("Command:", msg.topic, msg.payload.decode())
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID,
protocol=mqtt.MQTTv5)
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.will_set(STATUS, "offline", qos=1, retain=True)
client.reconnect_delay_set(min_delay=1, max_delay=120)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
connect_props = Properties(PacketTypes.CONNECT)
connect_props.SessionExpiryInterval = 3600 # keep session for 1 hour offline
client.connect(HOST, 8883, keepalive=60, clean_start=False, properties=connect_props)
client.loop_start()
while True:
reading = {"v": 1, "temp": 21.7, "ts": int(time.time())}
if client.is_connected():
client.publish(f"{BASE}/telemetry", json.dumps(reading), qos=0)
time.sleep(10)
To add jitter to the first reconnect across a fleet, sleep a random number of seconds before the initial connect call on boot.
Running the Checklist on ConnectMQ
On ConnectMQ, several items are handled for you or made easy to verify. Each broker gets generated credentials with client IDs bound to them, which enforces items 5 and 8. TLS on 8883 and Secure WebSocket on 8084 use Let's Encrypt certificates, which standard CA bundles trust. Flood protection and IP blocking after repeated failed logins add a layer you would otherwise build yourself.
For item 25, check the plan limits: the free Serverless plan supports up to 25 connections, QoS up to 1 and 256 KB messages; Serverless (Paid) supports up to 1,000 connections, QoS 2, 1 MB messages and shared subscriptions; Dedicated and BYOC give you isolated capacity. For items 28 and 29, use the portal's dashboard, live topic explorer and threshold alert rules with the alerts log, and subscribe to $SYS/broker/connection/{clientId}/state for critical gateways. A free Serverless broker also makes a good staging environment for item 30.
Get Started with ConnectMQ
Create your production-ready broker at app.connectmq.com, starting on the free Serverless plan with no credit card required. When you are ready to move beyond the pilot, read our guide to going from MQTT prototype to production, compare options in the cloud MQTT broker guide, or see what a hosted MQTT broker handles for you.
Frequently Asked Questions
What is the most commonly missed item before MQTT goes to production?
Reconnect behavior under real failures. Many teams test the happy path only, then discover reconnect storms or duplicate client IDs after the first outage.
Should production devices use QoS 2?
Rarely. QoS 1 with idempotent handling on the receiver covers most cases with less overhead; reserve QoS 2 for messages where duplicates are truly harmful.
Can I use the public test broker in production?
No. Public brokers are readable by anyone and have tight limits. Use a private broker with your own credentials and TLS.
How often should I rerun the checklist?
Before every launch and after significant firmware, backend or plan changes. Keep the evidence so audits and handovers are easy.



