MQTT Topic Builder
Build MQTT topics with + and # wildcards, validate hierarchy, and suggest patterns (Sparkplug B, Homie 4).
Designing MQTT topics that scale
MQTT (Message Queuing Telemetry Transport) is a lightweight publish/subscribe protocol designed in 1999 by Andy Stanford-Clark (IBM) and Arlen Nipper (Eurotech) to ship sensor data over the SCADA links of an oil pipeline. It became an OASIS standard in 2014 and is today the de-facto transport for IoT — millions of devices on satellite, NB-IoT, LoRa-gateways and home Wi-Fi feed brokers via MQTT because the protocol is tiny (2-byte fixed header), tolerates flaky links and works fine at 9.6 kbps.
A topic is the routing string that decouples publishers from subscribers. It is a hierarchical UTF-8 string with levels separated by forward slashes — home/livingroom/temperature, eu/factory1/sensor/123/temp. The broker never inspects the payload; only the topic matches subscriptions to publications. Good topic design is what keeps a fleet of 10k devices manageable; bad design turns every change into a fleet-wide refactor.
Wildcards and subscription rules
Wildcards exist only for subscriptions, never for publications. Two characters:
+matches a single level.home/+/temperaturecovers the temperature topic of every room.#matches all remaining levels and must be the last character.home/#sweeps the whole house.- Topics starting with
$(e.g.$SYS/broker/...) are reserved for broker metrics.#does not match them — subscribe explicitly. - MQTT 5 adds
$share/group/topicfor shared subscriptions — multiple consumers, one delivery, like a Kafka consumer group.
Best-practice topic structure
Established conventions across HiveMQ, EMQX and AWS IoT:
- Start with a constant — tenant, region, project. Makes ACL rules trivial.
- Most specific first within a domain —
region/site/device/sensor/metricreads top-down and subscribes well. - No leading slash —
/foois two levels (empty + "foo"); confusing and wasteful. - Lowercase, ASCII, no spaces — topics are case-sensitive, and slashes inside an identifier break the hierarchy.
- Cap depth around 7 levels — payload overhead, memory and ACL complexity grow linearly.
- Common splits:
tele/<device>/<metric>for telemetry,cmd/<device>/<action>for commands,status/<device>for heartbeat and LWT.
QoS, retain and the rest of the protocol
Three QoS levels balance reliability and overhead: 0 fire-and-forget, 1 at-least-once (may duplicate), 2 exactly-once (four-step handshake, rarely worth it). Retained messages deliver the last published value to any new subscriber instantly — perfect for current state. LWT (Last Will and Testament) publishes a goodbye message when the broker notices a client died — useful on status/<device>. MQTT 5 layers in user properties, message expiry, topic aliases (compress topic strings on the wire) and reason codes for richer error handling.
Brokers, profiles and security
Popular brokers: Mosquitto (Eclipse, simple), HiveMQ (commercial, MQTT 5 reference), EMQX (highly scalable, clustered), VerneMQ, Amazon IoT Core, Azure IoT Hub. Specialised profiles include Sparkplug B for industrial telemetry (Ignition SCADA), Homie for self-describing devices and MQTT-SN for very constrained transports (ZigBee, LoRa). Production traffic should run over TLS on port 8883 with client certificates or OAuth tokens — plain port 1883 is for development only.
FAQ
Are topics case-sensitive? Yes. Home/Temp and home/temp are different. Stick to lowercase to avoid mistakes.
What is the max depth? The MQTT spec allows up to 65535 bytes; the practical sweet spot is 5-7 levels. More than that gets hard to ACL and review.
Can I use wildcards when publishing? No. + and # only apply to subscriptions. A publish topic must be fully specified.
How do shared subscriptions work? MQTT 5 only. Subscribe to $share/workers/cmd/+ from N consumers and each message goes to exactly one of them — round-robin load balancing.
Plain TCP or TLS? Production is TLS on 8883. Use plain 1883 only inside a trusted LAN, otherwise credentials and payloads ride in the clear.
Related Tools
OKR Builder (1 Objective + 3 Key Results)
Takes one qualitative objective and three measurable key results and lays them out as a formatted OKR block ready to paste into a plan or review doc.
SSML Builder (Speech)
Build SSML (Speech Synthesis Markup) documents compatible with Alexa, Google and Polly with break, prosody, emphasis, phoneme and voice tags.
.netrc File Builder
Build a ~/.netrc file (curl, ftp, git credential) with multiple 'machine HOST' entries (login, password, optional account) and a single 'default' fallback. Rejects passwords with '#' or whitespace (which break parsers) and reminds you to chmod 600.
WebFinger JRD Builder (RFC 7033)
Build a JRD (JSON Resource Descriptor) for WebFinger (.well-known/webfinger) responses with acct: subject, aliases, properties and links (rel, type, href) — as used by Mastodon/ActivityPub.
Vue Component (Composition API)
Generate Vue 3 Composition API component skeleton (<script setup>) with props/ref/computed.
BLAKE3 Hash Generator
Educational BLAKE3 placeholder (sha-256 variant). For production use @noble/hashes.