These MQTT topic hierarchy examples give you ready-made trees for four common project types: a smart home, a vehicle fleet, a factory and an energy monitoring system. For each one you will see the tree, the subscriptions it is designed to serve and the decisions behind it, so you can adapt it instead of starting from a blank page.
Principles Behind Good MQTT Topic Hierarchies
Every tree below follows the same handful of rules. Knowing them makes it easier to bend the examples to your own project.
- Broad to narrow. Put the most general level first (site, home, fleet) and the most specific last (a single measurement or command).
- Fixed depth per kind of data. If every device's telemetry sits at the same level, a single
+pattern finds all of them. - Separate data by direction. Telemetry flows up, commands flow down. Give them different branches so devices only subscribe to what they need.
- Lowercase, no spaces, no leading slash.
home/kitchen/tempandHome/Kitchen/Tempare different topics; a leading/creates an empty first level. - Identifiers that survive changes. Use asset tags or serial numbers, not human labels that get renamed.
- Design for the subscriptions, not the publisher. Write down the wildcard queries consumers will run before you fix the tree.
The detailed reasoning is covered in MQTT topic naming conventions. Here we focus on concrete trees.
Smart Home Topic Hierarchy Example
A home has a natural structure: rooms contain devices, devices expose state and accept commands.
home/<room>/<device>/state # current state, retained
home/<room>/<device>/set # command to the device
home/<room>/<device>/availability # online/offline (Last Will)
home/<room>/<sensor>/<measurement> # numeric readings
home/livingroom/lamp/state -> {"on": true, "brightness": 70}
home/livingroom/lamp/set -> {"on": false}
home/kitchen/climate/temperature -> 21.4
home/kitchen/climate/humidity -> 48
home/garage/door/state -> "closed"
home/garage/door/availability -> "online"
| Consumer need | Subscription |
|---|---|
| Everything in the kitchen | home/kitchen/# |
| Every device state | home/+/+/state |
| Every temperature reading | home/+/+/temperature |
| Which devices are offline | home/+/+/availability |
Publish state and availability as retained messages so a dashboard that starts later immediately knows the current situation. Commands should not be retained, otherwise a device that reboots will replay yesterday's "open the garage door". For a deeper treatment of rooms, integrations and Home Assistant discovery, see the smart home MQTT topic structure guide.
Vehicle Fleet Topic Hierarchy Example
Fleet data is organised around vehicles, and consumers usually want either one vehicle's full picture or one data type across the fleet.
fleet/<region>/<vehicleId>/telemetry/<stream>
fleet/<region>/<vehicleId>/events/<eventType>
fleet/<region>/<vehicleId>/cmd/<command>
fleet/<region>/<vehicleId>/status
fleet/eu-west/van-0142/telemetry/gps -> {"lat": 51.51, "lon": -0.12, "spd": 34}
fleet/eu-west/van-0142/telemetry/engine -> {"rpm": 1800, "coolant": 88}
fleet/eu-west/van-0142/events/harsh-brake -> {"ts": 1792130400, "g": 0.52}
fleet/eu-west/van-0142/cmd/locate -> {}
fleet/eu-west/van-0142/status -> "online"
| Consumer need | Subscription |
|---|---|
| Live map for all vehicles | fleet/+/+/telemetry/gps |
| Everything from one van | fleet/+/van-0142/# |
| Driving-behaviour events in one region | fleet/eu-west/+/events/# |
Decisions worth copying:
- Region before vehicle. It lets you split processing by region later, for example with shared subscriptions per region worker group.
- Streams instead of one giant payload. GPS at one-second intervals and engine data every thirty seconds should not be forced into the same message.
- Commands per vehicle. Each vehicle subscribes to
fleet/<region>/<its id>/cmd/#and nothing else.
Factory Topic Hierarchy Example
In manufacturing the equipment hierarchy already exists in the plant's documentation, so the tree should mirror it. A simplified version:
<site>/<area>/<line>/<machine>/<namespace>/<detail>
plant1/assembly/line1/robot2/telemetry/joint-temps
plant1/assembly/line1/robot2/state
plant1/assembly/line1/robot2/alarms/overtemp
plant1/machining/line3/cnc1/telemetry/spindle
plant1/machining/line3/cnc1/cmd/stop
| Consumer need | Subscription |
|---|---|
| OEE service for one line | plant1/machining/line3/+/state |
| Maintenance view of every alarm | plant1/+/+/+/alarms/# |
| Historian for the whole site | plant1/# |
Keep the namespace vocabulary small and fixed: telemetry, state, alarms, events, cmd. When an integrator invents data, values and measurements for the same thing, every consumer has to learn three patterns.
Energy Monitoring Topic Hierarchy Example
Energy projects mix meters, inverters and batteries across buildings. The tree separates the physical location from the energy quantity being measured.
energy/<site>/<building>/<meterId>/<quantity>
energy/campus-a/building-3/main-meter/power -> 42.7 (kW)
energy/campus-a/building-3/main-meter/energy -> 18233.4 (kWh)
energy/campus-a/building-3/pv-inverter-1/power -> 12.1
energy/campus-a/building-3/battery-1/soc -> 76
energy/campus-a/building-3/battery-1/cmd/mode -> "discharge"
Include units in the documentation or the payload, never in the topic itself. A topic like .../power_kw becomes wrong the day someone publishes watts. A JSON payload such as {"v": 42.7, "unit": "kW", "ts": 1792130400} keeps the topic stable and the reading self-describing.
Ending With an ISA-95 Style Tree
When a project grows beyond one site or starts feeding a Unified Namespace, it usually converges on an ISA-95 style tree: enterprise, site, area, line, cell or machine, then a data namespace. This is also the shape ConnectMQ uses when it republishes Sparkplug B data into readable topics. A Sparkplug message on
spBv1.0/factory1/DDATA/line1/cnc1
is decoded and republished on
connectmq/factory1/production/line1/cnc1/telemetry
That gives you a full example of the target structure:
<enterprise>/<site>/<area>/<line>/<machine>/<namespace>
connectmq/factory1/production/line1/cnc1/telemetry
connectmq/factory1/production/line1/cnc1/state
connectmq/factory1/production/line2/press4/telemetry
connectmq/factory1/quality/lab/cmm1/events
The ConnectMQ portal recognises ISA-95 and Unified Namespace topics and shows devices grouped by those levels, so a disciplined tree pays off directly in the devices view. The ISA-95 MQTT topics article explains each level and its pitfalls, and the Sparkplug B and Unified Namespace guide covers how the two fit together.
Comparing the Four Trees
| Project | Top level | Identity level | Data split by | Typical depth |
|---|---|---|---|---|
| Smart home | home |
device in a room | state / set / measurement | 4 |
| Fleet | fleet |
vehicle in a region | telemetry / events / cmd | 4–5 |
| Factory | site | machine on a line | namespace | 5–6 |
| Energy | energy |
meter in a building | quantity | 5 |
Depth matters on real brokers. Some brokers limit topic levels, and every extra level costs bytes in every message. The public broker at broker.connectmq.com, for example, allows up to 8 topic levels, so a demo prefix such as connectmq/demo/<id> leaves five levels for your own tree.
Try a Tree on the Public Broker
You can prototype any of these hierarchies on the free public MQTT broker before committing to it. Use a unique prefix, because the public area is readable by everyone, and keep data non-sensitive.
# Subscriber: all device states in your demo home
mosquitto_sub -h broker.connectmq.com -p 1883 -i tree-sub-a91c \
-t 'connectmq/demo/a91c/home/+/+/state' -v
# Publisher: a retained lamp state
mosquitto_pub -h broker.connectmq.com -p 1883 -i tree-pub-a91c -r \
-t 'connectmq/demo/a91c/home/livingroom/lamp/state' \
-m '{"on": true, "brightness": 70}'
That example uses seven levels, which fits within the public broker limit. If the subscriber sees the lamp state, your wildcard plan works. Then try connectmq/demo/a91c/home/livingroom/# and confirm it returns only the living room. If the tree is new to you, the MQTT wildcards guide explains exactly how + and # match each level, and the MQTT tutorial covers the publish and subscribe basics.
Common Mistakes in Topic Hierarchies
- Putting the data type first.
temperature/kitchenscatters each device across many branches and makes per-device subscriptions awkward. - Encoding values in topics.
home/lamp/onandhome/lamp/offas topics means consumers subscribe to both; publish the value as a payload. - One topic per message ID or timestamp. Topics are addresses, not records. Unique topics per message bloat retained storage and topic lists.
- Mixed separators.
line-1,line_1andLine1in the same tree will break someone's wildcard eventually. Pick one style. - No command branch. If commands share a topic with telemetry, devices receive their own data back and need extra filtering.
Get Started with ConnectMQ
When your tree is ready for real devices, run it on a cloud MQTT broker with TLS and private credentials. Create a free Serverless broker at app.connectmq.com, no credit card needed, and watch your hierarchy fill in with the live topic explorer and the ISA-95 devices view.
Frequently Asked Questions
How deep should an MQTT topic hierarchy be?
Deep enough to identify the source and the kind of data, usually four to six levels. More levels add bytes to every message and may hit broker limits without adding useful structure.
Should the device ID or the data type come first?
Put location and device identity first, then the data type. That keeps all data from one device under one branch and still lets + wildcards select a data type across devices.
Can I change my topic hierarchy later?
Yes, but every publisher and subscriber has to change with it. A common migration path is to publish to both the old and new trees for a transition period, then retire the old one once consumers have moved.
Do I need ISA-95 for a small project?
No. A simple tree like the smart home example is fine for small projects. ISA-95 style trees pay off once several sites, teams or systems share one namespace.



