IoT Automation

Smart Home MQTT Topic Structure: Best Practices for Rooms, Devices and Commands

A clean topic layout makes every smart home automation easier. Learn a room/device/property scheme, how to separate command and state topics, when to retain, and which naming mistakes to avoid.

Smart home MQTT topic structure diagram showing rooms, devices and properties branching from a home root topic
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

A good smart home MQTT topic structure is the difference between automations you can read at a glance and a tangle of sensor1/temp2 topics nobody remembers. In this guide you will get a ready-to-use room/device/property layout, learn why command and state topics must be separate, and see how retained messages, availability and wildcards fit together on a real broker.

Why Topic Design Matters Before the Tenth Device

With three devices, any naming works. By the time you have thirty, topic names decide how easy it is to:

  • subscribe to "everything in the kitchen" or "every temperature in the house" with one wildcard,
  • add a new device without editing every automation,
  • tell whether a message is a request or a fact,
  • see in a topic explorer what is actually happening.

MQTT does not enforce any structure. Topics are just UTF-8 strings split by /, and the broker matches subscriptions against them. That freedom is exactly why you need a convention. If the basics of how the broker routes these messages are new to you, start with what an MQTT broker does.

A layout that scales well for most homes is:

<home>/<room>/<device>/<property>[/set]

Examples:

home1/kitchen/ceiling-light/power            state: "ON" or "OFF" (retained)
home1/kitchen/ceiling-light/power/set        command: "ON", "OFF", "TOGGLE"
home1/kitchen/ceiling-light/brightness       state: 0-100 (retained)
home1/kitchen/ceiling-light/brightness/set   command: 0-100
home1/livingroom/climate/temperature         state: 21.6 (retained)
home1/livingroom/climate/humidity            state: 48 (retained)
home1/garage/door/state                      state: "open", "closed", "opening" (retained)
home1/garage/door/state/set                  command: "OPEN", "CLOSE"
home1/garage/door/availability               "online" or "offline" (retained, last will)

Why this order works:

Level Purpose Wildcard example
home Separates sites (house, holiday flat, parents' home) home1/#
room Matches how people think and speak home1/kitchen/#
device One physical or logical device home1/+/climate/#
property One value or capability home1/+/+/temperature
set suffix Marks a command, not a fact home1/+/+/+/set

Keep the depth at five levels or fewer. Deep trees are harder to type and the public test broker limits topics to eight levels anyway, which is a sensible ceiling for a home.

Command vs State Topics in a Smart Home MQTT Topic Structure

The single most important rule: never use the same topic for commands and state.

If a light listens and reports on home1/kitchen/ceiling-light/power, then a dashboard that publishes ON will see its own message echoed back, cannot tell whether the light actually switched, and a retained ON command will turn the light back on every time the device reconnects, even after someone switched it off at the wall.

With separate topics the flow is unambiguous:

  1. The dashboard publishes ON to .../power/set (not retained).
  2. The device switches the relay.
  3. The device publishes ON to .../power with the retain flag.
  4. Every subscriber, including the dashboard, updates from the state topic.

The state topic becomes the single source of truth. Commands are requests that may fail; states are facts the device confirms.

Retain state, never retain commands

Retained messages let a newly connected client see current state immediately. That is exactly what you want for states and availability, and exactly what you do not want for commands. A retained OPEN on a garage door command topic is a door that opens itself after every power cut. Our MQTT garage door opener tutorial shows this pattern in a project where getting it wrong has real consequences.

Choose QoS per topic type

States from sensors are fine at QoS 0 or 1; a missed temperature is replaced by the next one. Commands should use QoS 1 so they are delivered at least once, and devices should treat repeated commands as idempotent (ON twice is still on). For the trade-offs, see MQTT QoS levels explained.

Availability and Last Will

Every device should publish an availability topic. Set it to online (retained) after connecting and configure a last will message of offline (retained) on the same topic. If the device loses power or Wi-Fi, the broker publishes the will for it, and dashboards can grey out the device instead of showing a stale value as current.

// ESP32 with PubSubClient: last will on connect, then announce online
const char* AVAIL = "home1/garage/door/availability";
if (mqtt.connect(clientId, user, pass, AVAIL, 1, true, "offline")) {
  mqtt.publish(AVAIL, "online", true);
  mqtt.subscribe("home1/garage/door/state/set", 1);
}

Payload Conventions

Topic structure and payload format go together. Pick one approach and use it everywhere:

  • One value per topic (.../temperature = 21.6) is simple, works with every tool, and makes wildcards powerful.
  • JSON per device (.../climate = {"temperature":21.6,"humidity":48}) reduces message count and keeps related values consistent.

Many homes use both: JSON for multi-sensor devices from Zigbee2MQTT or ESPHome, single values for DIY devices. If you do use JSON, document the keys and include units either in the key name (temp_c) or a schema note. Avoid mixing 21.6, "21.6" and "21.6 C" across devices.

Naming Rules That Prevent Pain

  1. Use lowercase, hyphen-separated names: ceiling-light, not Ceiling Light.
  2. No spaces, no # or + in names, no leading / (it creates an empty first level).
  3. Name rooms as people do, but avoid names that change (toms-room becomes awkward when Tom moves out; bedroom-2 lasts).
  4. Name devices by function, not brand or model, so you can replace hardware without renaming.
  5. Reserve a top-level prefix for system topics such as home1/system/backup-status.
  6. Never put secrets, door codes or personal data in topic names; topics are visible to every subscriber with matching wildcards.

Integrating Ecosystem Topics

You will not control every topic name. Zigbee2MQTT publishes under zigbee2mqtt/<friendly_name>, Tasmota uses stat/, tele/ and cmnd/ prefixes, and Home Assistant discovery uses homeassistant/<component>/<id>/config. Do not fight these conventions. Instead:

  • Give devices friendly names that follow your room/device pattern, for example kitchen/ceiling-light in Zigbee2MQTT, so its topics become zigbee2mqtt/kitchen/ceiling-light.
  • Keep your own DIY devices under your home1/ root.
  • Let Home Assistant map everything into entities via MQTT discovery.

Our Zigbee2MQTT setup guide shows how friendly names translate into topics.

Try the Layout on a Public Broker

You can test the structure without hardware. Use a random prefix so your topics do not collide with anyone else's:

# Terminal 1: watch the whole house
mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-h7q2 -t "connectmq/demo/h7q2/home1/#" -v

# Terminal 2: a light reports retained state, then a dashboard sends a command
mosquitto_pub -h broker.connectmq.com -p 1883 -i light-h7q2 -r -q 1 \
  -t connectmq/demo/h7q2/home1/kitchen/ceiling-light/power -m ON
mosquitto_pub -h broker.connectmq.com -p 1883 -i dash-h7q2 -q 1 \
  -t connectmq/demo/h7q2/home1/kitchen/ceiling-light/power/set -m OFF

# Every temperature in the house, any room, any device
mosquitto_sub -h broker.connectmq.com -p 1883 -i temps-h7q2 -t "connectmq/demo/h7q2/home1/+/+/temperature" -v

The demo prefix adds three levels, which is one more reason to keep your own tree shallow. The public area is readable by everyone, so use it for structure experiments only, not for your real home. When you move to a private broker you can drop the demo prefix and start at home1/.

Smart Home Topic Structure Checklist

  1. Every device follows <home>/<room>/<device>/<property>.
  2. Commands use a /set suffix and are never retained.
  3. States are retained and published by the device after it acts.
  4. Every device has an availability topic with a last will.
  5. Names are lowercase, hyphenated and function-based.
  6. Payload format is documented and consistent.
  7. Topic depth stays at five levels or fewer.

Running Your Home on a Private Broker

A topic structure only stays clean if the broker it lives on is secure and reliable. ConnectMQ offers a managed MQTT broker with TLS on port 8883, generated credentials and a live topic explorer where your room/device tree is easy to browse. If you are deciding between hosting yourself and using a cloud MQTT broker, think about remote access, certificates and updates. For more home and building projects, see the IoT automation guide.

Get Started with ConnectMQ

Create a free Serverless broker at app.connectmq.com, no credit card required, copy your generated credentials and publish your first home1/ topics. The ConnectMQ live topic explorer shows your whole house as a tree within seconds.

Frequently Asked Questions

Should topics start with a slash?

No. A leading slash creates an empty first level, which is legal but confusing and easy to mistype. Start with your home or site name.

Is it better to use one JSON topic per device or one topic per value?

Both work. One value per topic is simplest for wildcards and DIY devices; JSON per device suits multi-sensor devices. Pick one per device type and document it.

Why is my light turning on by itself after a reboot?

You probably retained a command message. Clear it by publishing an empty retained message to the command topic, and only retain state topics from now on.

How many topic levels should a smart home use?

Four or five is plenty: home, room, device, property and an optional set suffix. Deeper trees add typing and little value.

Related articles

Zigbee2MQTT Setup Guide: From Coordinator to Dashboard

Install Zigbee2MQTT with Docker, configure the coordinator and MQTT connection, pair and rename devices, control them over MQTT and view their states on a dashboard, testing first on a free public broker.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.