MQTT MESSAGING

The dominant pub/sub protocol for IoT. Broker architecture, QoS, topic design, TLS, retained messages, LWT, and production deployment for ESP32 and cloud platforms.

IOT LIVE PUB/SUB v3.1.1 v5.0 TLS ESP-IDF
@mqtt
01

OVERVIEW

MQTT (Message Queuing Telemetry Transport) is a lightweight publish/subscribe messaging protocol designed for constrained devices on unreliable networks. It runs over TCP, uses a central broker, and provides three QoS levels from fire-and-forget to exactly-once delivery.

Transport
TCP :1883 / :8883 TLS
Model
Publish / Subscribe
Versions
v3.1.1 + v5.0
Max Payload
256 MB (typ. 1-4 KB)
QoS Levels
3
Encoding
Binary (efficient)
02

QOS LEVELS

QoSGuaranteePacketsUse Case
0At most once (fire & forget)PUBLISH onlySensor telemetry (high freq, loss OK)
1At least once (may duplicate)PUBLISH + PUBACKAlerts, commands (idempotent handlers)
2Exactly once4-packet handshakeOTA triggers, financial (expensive)
QoS 2 at Scale

Never use QoS 2 for high-frequency telemetry. The 4-packet handshake per message creates 4x overhead and bottlenecks the broker. Use QoS 0 for telemetry, QoS 1 for commands, QoS 2 only for critical one-shot events.

03

TOPIC ARCHITECTURE

Naming Convention

{org}/{site}/{zone}/{device_type}/{device_id}/{data_type}

2nth/hillcrest-dc/zone-a/temp-sensor/ts-001/telemetry
2nth/hillcrest-dc/zone-a/temp-sensor/ts-001/status
2nth/hillcrest-dc/zone-a/temp-sensor/ts-001/cmd

Wildcards

  • + single level: 2nth/+/zone-a/+/+/telemetry
  • # multi-level: 2nth/hillcrest-dc/#
  • Subscribe-only — cannot publish to wildcard topics

Retained Messages & Last Will

Retained: Broker stores last message per topic. New subscribers get current state immediately. Essential for device status and config.

LWT (Last Will and Testament): Set at CONNECT time. Broker auto-publishes if client disconnects ungracefully — instant offline detection.

04

BROKER SELECTION

Open Source

BrokerLanguageClusteringBest For
MosquittoCBridge onlySingle-node, <100K conn, edge
EMQXErlangBuilt-inProduction cloud, >100K conn
NanoMQCNoEdge gateway, embedded
VerneMQErlangYesMid-scale production

Managed Cloud

ServiceMax MsgBest For
AWS IoT Core128 KBAWS-native, device shadows, fleet
Azure IoT Hub256 KBAzure-native, device twins
HiveMQ Cloud256 MBEnterprise, automotive
Cloudflare Pub/Sub1 MBWorkers integration, edge
05

ESP32 MQTT CLIENT

ESP-IDF (Production)

#include "mqtt_client.h"

esp_mqtt_client_config_t cfg = {
    .broker.address.uri = "mqtts://mqtt.2nth.io:8883",
    .broker.verification.certificate = server_cert_pem,
    .credentials.username = "device01",
    .credentials.authentication.password = "secret",
    .session.last_will = {
        .topic = "device/status",
        .msg = "{\"online\":false}",
        .qos = 1, .retain = true,
    },
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&cfg);
esp_mqtt_client_start(client);

// Publish telemetry
esp_mqtt_client_publish(client,
    "device/telemetry",
    "{\"temp\":24.5,\"heap\":280000}", 0, 0, 0);

Arduino (PubSubClient)

#include <WiFi.h>
#include <PubSubClient.h>

WiFiClient espClient;
PubSubClient mqtt(espClient);
mqtt.setServer("mqtt.2nth.io", 1883);
mqtt.connect("esp32-device", "user", "pass");
mqtt.subscribe("device/cmd");
mqtt.publish("device/telemetry", "{\"temp\":24.5}");
06

SECURITY

Always use TLS (port 8883) in production. Plaintext MQTT on 1883 is unacceptable for anything beyond local development.

MethodStrengthBest For
Username/PasswordBasicDev, small deploys
Client certs (mTLS)StrongProduction fleet
JWT tokensStrongCloud-native, rotating creds
Topic ACLsAdditiveAll deployments
Device Identity

For production fleets, use mTLS with per-device client certificates. Each device gets a unique cert at provisioning, and the broker ACL restricts it to its own topic subtree. This is the gold standard for IoT device auth.

07

SCALING PATTERNS

Bridge Pattern (Edge to Cloud)

Edge Broker (NanoMQ)              Cloud Broker (EMQX)
  Local devices publish             Aggregated telemetry
  Low-latency local rules           Dashboard / API
  Offline buffering                 Rules engine -> DB
  Bridge forwards to cloud -------> Fleet management

Shared Subscriptions (v5)

# Three workers share the load — each msg to only one
Worker-1: SUBSCRIBE $share/workers/telemetry/#
Worker-2: SUBSCRIBE $share/workers/telemetry/#
Worker-3: SUBSCRIBE $share/workers/telemetry/#

Sparkplug B (Industrial)

Standardised topic namespace with birth/death certificates, Protobuf payloads, and state management for industrial IoT. Topic format: spBv1.0/{group}/{type}/{edge_node}/{device}

08

PAYLOAD FORMATS

FormatSizeSchemaBest For
JSONBaselineSchema-lessMost IoT (human-readable)
CBOR20-40% smallerSchema-lessConstrained devices (tinycbor)
ProtobufSmallest.proto requiredBandwidth-critical (nanopb)
09

KEY GITHUB REPOSITORIES

RepoPurpose
eclipse/mosquittoReference MQTT broker (C)
emqx/emqxScalable Erlang broker
nanomq/nanomqEdge-native C broker
espressif/esp-mqttESP-IDF MQTT client
knolleary/pubsubclientArduino MQTT client
mqttjs/MQTT.jsNode.js / browser client
hivemq/hivemq-ceJava broker (community)