Topics and wildcards
A topic is the address of a message. A publisher puts a topic name on every PUBLISH, a subscriber registers a
topic filter, and the broker delivers each message to every client whose filter matches it. Nothing is declared in
advance: a topic exists because someone published to it, and it stops existing when nobody does.
Topics are hierarchical — a forward slash separates levels — and that hierarchy is what lets one subscription cover a
whole fleet. sensors/livingroom/temperature has three levels, and a filter that pins the first and last while
wildcarding the middle follows every room at once. For the protocol rules and a wider set of examples, see the
MQTT topics guide.
Topic names and topic filters
Section titled “Topic names and topic filters”The specification keeps the two ideas apart, and TBMQ enforces the distinction:
- A topic name is what a publisher sends. It must not contain a wildcard character, and TBMQ rejects a topic name that
begins with
$, which is reserved. - A topic filter is what a subscriber sends. It may contain wildcards, and it may use the reserved
$share/prefix that turns the subscription into a shared subscription.
Both are case-sensitive, and both count empty levels — so sensors/temp, sensors/Temp and /sensors/temp are three
distinct addresses. Neither is checked against a schema, which means a typo in a publisher’s topic silently creates a new
topic with no subscribers rather than raising an error.
Wildcards
Section titled “Wildcards”Two wildcard characters may appear in a filter:
| Wildcard | Matches | Example filter | Example matches |
|---|---|---|---|
+ |
Exactly one level, whatever it contains | sensors/+/temperature |
sensors/livingroom/temperature, but not sensors/temperature |
# |
The level it sits at and every level below it | sensors/# |
sensors, sensors/livingroom, sensors/livingroom/temperature |
A wildcard occupies a whole level, never part of one, and # must be the last character of the filter — so sensors/+/state
is valid while sensors/te+p and sensors/#/state are rejected. Neither wildcard reaches above the level it starts at:
sensors/# does not match /sensors, because the leading slash makes the first level empty and therefore different.
Why the hierarchy design matters
Section titled “Why the hierarchy design matters”Matching a published topic is a walk down the topic tree, so the shape you choose decides which slices consumers are able
to select at all. Put the stable categories near the root and the volatile identifiers near the leaves:
{region}/{plant}/{device-id}/telemetry lets a consumer follow one plant, one device, or everything, whereas
{device-id}/{region}/{plant}/telemetry supports none of those. Depth costs a little on every message, and TBMQ can
enforce a ceiling on how deep a topic may go if you want a hard guarantee.
MQTT 5.0 clients can also stop resending a long topic name on every message by agreeing a numeric Topic Alias with the broker for the lifetime of the connection. TBMQ supports this and enables it by default.
For the full wildcard reference, the naming conventions to follow, and the topic limits TBMQ enforces, see Topics.
Was this helpful?