MQTT topic naming conventions decide whether your system stays easy to subscribe to, secure and debug as it grows from five devices to five thousand. This guide gives you 12 concrete rules with good and bad examples, a reusable template, and a checklist you can apply before the first device ships.
Why Topic Names Deserve a Convention
MQTT topics are free-form UTF-8 strings separated by /. The broker does not enforce any structure, and topics are created on the fly when someone publishes. That freedom is convenient on day one and painful on day 300, when subscribers rely on dozens of slightly different spellings, wildcards match the wrong data, and nobody dares rename anything because unknown consumers might break.
Topic names are effectively the public API of your system. Every subscriber, dashboard, Node-RED flow and access rule depends on them. Agreeing on a convention early is one of the cheapest reliability improvements available.
The 12 MQTT Topic Naming Conventions
1. Do Not Start With a Slash
A leading / creates an empty first level. /factory/line1 and factory/line1 are different topics, and the empty level adds nothing but confusion.
- Bad:
/factory/line1/temp - Good:
factory/line1/temp
2. Use Lowercase Only
Topics are case-sensitive. Line1/Temp and line1/temp are different topics, and mixed case guarantees someone subscribes to the wrong one. Pick lowercase and stick to it.
3. Avoid Spaces and Special Characters
Spaces, accents and symbols are legal but cause escaping problems in shells, URLs, logs and configuration files. Use a-z, 0-9, - and _. Never use + or # inside names; they are wildcard characters in subscriptions.
- Bad:
Plant A/Pump #3/Pressure (bar) - Good:
plant-a/pump-3/pressure
4. Go From General to Specific
Order levels from the broadest scope to the narrowest, so wildcards can select whole branches. A common shape is:
<namespace>/<site>/<area>/<line-or-group>/<device>/<category>/<measurement>
With this order, acme/berlin/# selects one site and acme/+/+/+/+/telemetry/temperature selects every temperature reading. The opposite order makes such subscriptions impossible. See MQTT wildcards for how + and # match.
5. Start With a Namespace
A first level such as your company, product or application name keeps your traffic separate from other systems sharing the same broker, and makes bridging or migrating easier later. On the public test broker, a unique prefix such as connectmq/demo/<random-id>/ keeps your experiments out of everyone else's way.
6. Put Device IDs After the Location, Not Before
Identifiers belong at the level that represents the device, after the grouping levels that describe where it lives. This lets you subscribe to a location without knowing every device ID, and to a single device with one exact topic.
- Bad:
esp32-a4cf12/berlin/hall2/temperature - Good:
acme/berlin/hall2/esp32-a4cf12/telemetry/temperature
7. Separate Message Categories
Keep telemetry, state, commands and events in different branches. Subscribers and access rules can then target exactly what they need.
| Category | Example topic | Typical QoS / retain |
|---|---|---|
| Telemetry | acme/berlin/hall2/pump-3/telemetry/pressure |
QoS 0, not retained |
| State | acme/berlin/hall2/pump-3/state/running |
QoS 1, retained |
| Status | acme/berlin/hall2/pump-3/status |
QoS 1, retained, set by Last Will |
| Commands | acme/berlin/hall2/pump-3/cmd/set-speed |
QoS 1, not retained |
| Events / alarms | acme/berlin/hall2/pump-3/event/overpressure |
QoS 1, not retained |
8. Version Your Payload Contract
When payload formats change, consumers break. Put a version where it is easy to route on, either as a topic level (acme/v2/...) or as a field inside every payload. A topic version lets old and new consumers run side by side during migration.
9. Keep It Shallow Enough
Every level should carry meaning. Seven or eight levels is plenty for most systems, and some brokers enforce a limit; the ConnectMQ public test broker allows up to 8 levels. Deep trees also cost bandwidth, because the full topic string is sent with every message (MQTT 5 topic aliases help, but do not fix bad design).
10. Do Not Put Data or Secrets in the Topic
Values, timestamps, tokens and personal data belong in the payload. A topic like acme/pump-3/pressure/4.2 creates a new topic for every reading and breaks retained messages and subscriptions. Topic names also appear in logs and monitoring tools, so never include credentials or personal information.
11. Use Singular, Stable Nouns
Pick one word per concept and document it: temperature, not temp in one place and Temperature_C in another. Units belong in the payload or documentation rather than the topic name, unless the same measurement is genuinely published in several units.
12. Reserve $ for the Broker
Topics starting with $ are reserved for broker-internal use, such as $SYS/... statistics, and are not matched by a plain # subscription. Do not create your own $ topics. Learn what your broker publishes there in MQTT $SYS topics.
Good and Bad Topic Trees Side by Side
# Hard to use
/Factory1/Line 1/CNC#1/Temp
cnc1/factory1/temperature/71.3
Factory1/line1/CNC1/TEMP_C
# Easy to use
acme/factory1/machining/line1/cnc1/telemetry/spindle-temperature
acme/factory1/machining/line1/cnc1/state/mode
acme/factory1/machining/line1/cnc1/status
acme/factory1/machining/line1/cnc1/cmd/start
The second tree follows the ISA-95 style enterprise, site, area, line and cell hierarchy often used for a Unified Namespace. If you work in industrial settings, the Sparkplug B and Unified Namespace guide explains how these hierarchies are standardised. For more ready-made trees, browse our MQTT topic hierarchy examples.
Try Your Convention on a Live Broker
Publish a few messages using your proposed structure to the free public MQTT broker and check that wildcard subscriptions select exactly what you expect. Replace n8x4 with your own random string; the public area is readable by everyone. The demo drops the area level so the full topic stays within the public broker's 8-level limit.
P="connectmq/demo/n8x4/factory1/line1"
mosquitto_pub -h broker.connectmq.com -p 1883 -i naming-pub-n8x4 \
-t "$P/cnc1/telemetry/spindle-temperature" -m '{"v":71.3,"unit":"C"}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i naming-pub-n8x4 \
-t "$P/cnc2/telemetry/spindle-temperature" -m '{"v":68.9,"unit":"C"}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i naming-pub-n8x4 \
-r -q 1 -t "$P/cnc1/status" -m 'online'
# All telemetry from line1, nothing else
mosquitto_sub -h broker.connectmq.com -p 1883 -i naming-sub-n8x4 -v \
-t "connectmq/demo/n8x4/factory1/line1/+/telemetry/#"
Only the retained status message would have been delivered immediately to a fresh subscriber; the telemetry above was published before the subscriber connected and was not retained. Publish again with the subscriber running to see it arrive.
Topic Convention Checklist
- A written document lists every level, its meaning and allowed values.
- All topics are lowercase, without leading slash, spaces or wildcard characters.
- A namespace is the first level.
- Levels go from general to specific, with the device ID after its location.
- Telemetry, state, status, commands and events have separate branches.
- A versioning strategy exists.
- No values, timestamps or secrets appear in topics.
- Depth stays within broker limits.
- Wildcard subscriptions for every known consumer have been tested.
- The tree has been reviewed in a topic browser with realistic data.
If you are at the very beginning, the MQTT tutorial covers topics, subscriptions and QoS together.
See Your Topic Tree in ConnectMQ
ConnectMQ gives every broker a live topic explorer, so you can see your hierarchy grow in real time and spot stray spellings immediately. It also recognises ISA-95 and Unified Namespace style topics and shows devices by ISA-95 level, which rewards a disciplined convention. As a hosted MQTT broker it supports MQTT 3.1.1 and 5.0 on TCP, TLS and WebSockets. Create a free Serverless broker, no credit card required, and test your topic convention with real devices.
Frequently Asked Questions
Should MQTT topics start with a slash?
No. A leading slash creates an empty first topic level, which makes topics harder to read and easy to mistype. Start directly with your namespace, such as acme/....
Are MQTT topics case-sensitive?
Yes. Sensor/Temp and sensor/temp are completely different topics. Using lowercase everywhere avoids accidental mismatches.
How many levels should an MQTT topic have?
As many as carry meaning and no more; most systems need between four and eight. Check broker limits too: the ConnectMQ public test broker allows up to 8 levels.
Where should the device ID go in an MQTT topic?
After the levels that describe location or grouping, and before the message category and measurement. That order lets wildcards select a site, a line or a single device cleanly.



