Ein Sensor sendet Daten, ein Dienst verarbeitet sie und plötzlich empfängt ein falscher Verbraucher dieselbe Nachricht. Genau hier entscheidet die Topic-Struktur darüber, ob eine MQTT-Umgebung übersichtlich bleibt oder im Betrieb schwer beherrschbar wird. Ich zeige, wie MQTT-Topics aufgebaut sind, wie Wildcards funktionieren und worauf es bei Hosting, Sicherheit und DevOps ankommt.
Eine klare Topic-Hierarchie macht MQTT skalierbar und sicher
- Topics sind hierarchische Adressen für Nachrichten im MQTT-Broker.
- Topic Names werden beim Veröffentlichen genutzt, Topic Filter beim Abonnieren.
- + ersetzt genau eine Ebene, # beliebig viele Ebenen.
- Eine Struktur wie prod/factory-01/device-017/telemetry/temperature bleibt auch bei vielen Geräten verständlich.
- TLS, ACLs und Monitoring gehören bereits beim Entwurf zur Topic-Strategie.

Was ein MQTT-Topic im Broker wirklich leistet
Ein MQTT-Topic ist eine hierarchische Adresse, unter der ein Client eine Nachricht veröffentlicht. Der Broker nimmt diese Nachricht entgegen und verteilt sie an alle Abonnenten, deren Filter auf diese Adresse passt. Publisher und Subscriber müssen sich dabei nicht direkt kennen.
Ein mögliches Topic lautet prod/factory-01/device-017/telemetry/temperature. Der Schrägstrich teilt die Adresse in Ebenen auf. MQTT schreibt nicht vor, was die einzelnen Ebenen bedeuten. Diese Bedeutung legt das Team selbst fest, und genau deshalb sollte die Namenskonvention vor dem ersten produktiven Gerät dokumentiert werden.
Topic Name und Topic Filter sind nicht dasselbe
Beim Veröffentlichen wird ein konkreter Topic Name verwendet. Er darf keine Wildcards enthalten. Beim Abonnieren kommt dagegen ein Topic Filter zum Einsatz, der mit + oder # mehrere Adressen abdecken kann.
mosquitto_pub -t "prod/factory-01/device-017/telemetry/temperature" -m "21.7"
mosquitto_sub -t "prod/factory-01/+/telemetry/+"MQTT-Topics sind unterscheidet zwischen Groß- und Kleinschreibung. Temperature, temperature und /temperature sind verschiedene Namen. Auch Leerzeichen sind technisch zulässig, in einer produktiven Konvention würde ich sie trotzdem vermeiden.
Die Spezifikation erlaubt Topic-Namen mit bis zu 65.535 UTF-8-Bytes. Das ist eine Obergrenze, aber kein gutes Designziel. Kurze, stabile und lesbare Ebenen erleichtern ACLs, Logs, Dashboards und Fehlersuche erheblich.
Eine Topic-Hierarchie, die mit dem System wächst
Eine gute Hierarchie beantwortet schon beim Lesen drei Fragen: Zu welcher Umgebung gehört die Nachricht? Welcher Standort oder Mandant ist betroffen? Handelt es sich um Telemetrie, Zustand, Befehl oder ein Ereignis?
Für eine industrielle Plattform kann diese Struktur funktionieren:
prod/factory-01/line-02/device-017/telemetry/temperature
prod/factory-01/line-02/device-017/state/online
prod/factory-01/line-02/device-017/cmd/set-mode
prod/factory-01/line-02/device-017/event/faultDie Reihenfolge ist nicht vorgeschrieben. Sie sollte aber zu den häufigsten Abfragen und Berechtigungen passen. Wenn ein Team regelmäßig alle Geräte eines Standorts abonniert, gehören Standort und Umgebung weit nach vorn. Ich halte prod und staging in getrennten Topic-Bäumen für deutlich sicherer, als die Trennung nur über Client-Namen oder Payload-Felder abzubilden.
| Nachrichtenart | Beispiel | Typischer Zweck |
|---|---|---|
| Telemetrie | .../telemetry/temperature |
Messwerte für Speicherung, Analyse und Dashboards |
| Zustand | .../state/online |
Aktueller Status eines Geräts, oft als Retained Message |
| Befehl | .../cmd/set-mode |
Gezielte Anweisung an ein Gerät oder einen Dienst |
| Ereignis | .../event/fault |
Einmaliges Ereignis wie Fehler, Neustart oder Alarm |
Was nicht in ein Topic gehört
Zeitstempel, Messwerte und große Metadaten gehören normalerweise in die Nachricht, nicht in die Adresse. Ein Topic wie temperature/2026/08/18/14/32/21 erzeugt eine unübersichtliche Struktur und erschwert Abonnements. Besser ist ein stabiler Topic Name mit einem Payload, der Zeit, Einheit und Wert enthält.
Auch Passwörter, E-Mail-Adressen oder andere personenbezogene Daten haben im Topic nichts verloren. Topic-Namen tauchen in Logs, Metriken und Berechtigungsregeln auf und sind deshalb oft sichtbarer als gedacht. Für Mandanten empfiehlt sich eine feste Mandantenebene wie prod/tenant-a/..., kombiniert mit passenden ACLs.
Wildcards und gemeinsame Abonnements richtig einsetzen
Wildcards gelten nur für Topic Filter beim Abonnieren. Das Pluszeichen + ersetzt genau eine Ebene, während das Rautezeichen # die aktuelle Ebene und alle darunterliegenden Ebenen abdeckt.
| Filter | Passt auf | Passt nicht auf |
|---|---|---|
prod/+/+/state/online |
Online-Status aller Geräte in zwei festen Ebenen | Zusätzliche oder fehlende Ebenen |
prod/factory-01/# |
Alle Nachrichten unterhalb des Werks | Andere Umgebungen oder Werke |
.../telemetry/+ |
Eine Telemetrieart, etwa Temperatur | .../telemetry/room/temperature |
# |
Alle passenden Nachrichten des Brokers | Reservierte Bereiche mit führendem $ können ausgenommen sein |
Ein häufiger Fehler ist sensor/temperature+. Das ist keine gültige Plus-Wildcard, weil + eine komplette Ebene ersetzen muss. Ebenso muss # am Ende stehen, etwa sensor/temperature/#.
Für Debugging ist # praktisch, im Dauerbetrieb aber gefährlich. Ein Entwickler-Client kann damit vertrauliche Nachrichten empfangen, unnötige Last erzeugen oder versehentlich große Datenmengen verarbeiten. Ich beschränke breite Filter deshalb auf temporäre Diagnosekonten und sichere sie zusätzlich über ACLs.
Shared Subscriptions für Worker
Normale Abonnements verteilen eine Nachricht an jeden passenden Subscriber. Das ist für mehrere Dashboards sinnvoll, aber nicht für zehn identische Worker, die gemeinsam eine Aufgabenwarteschlange abarbeiten sollen. Dafür können MQTT-5-Broker gemeinsame Abonnements unterstützen:
$share/image-workers/prod/media/jobsAlle Worker derselben Gruppe teilen sich die Nachrichten. Eine einzelne Nachricht wird dabei an einen Client aus dieser Gruppe zugestellt. Das ist nützlich für Skalierung, ersetzt aber keine vollständige Queue-Strategie. Bei einem Neustart oder Fehler hängt das Verhalten von QoS, Session-Einstellungen und Broker-Konfiguration ab.
Topic-Design mit QoS, Retain und Zuständen verbinden
Die Adresse allein garantiert weder Zustellung noch Aktualität. Dafür sind vor allem QoS, Retain und Session-Verhalten entscheidend. Diese Eigenschaften sollten deshalb gemeinsam mit der Topic-Konvention dokumentiert werden.
| QoS | Bedeutung | Geeignet für |
|---|---|---|
| 0 | Keine zusätzliche Zustellbestätigung | Häufige Messwerte, bei denen der nächste Wert bald folgt |
| 1 | Mindestens einmal, Duplikate sind möglich | Befehle und Ereignisse mit idempotenter Verarbeitung |
| 2 | Aufwendigeres Protokoll für genau einmalige Zustellung | Wenige kritische Nachrichten, wenn der Mehraufwand gerechtfertigt ist |
QoS 1 bedeutet nicht, dass eine Nachricht in der Anwendung nur einmal verarbeitet wird. Bei Wiederholungen muss der Consumer Duplikate erkennen können, etwa über eine Nachrichten-ID. In vielen IoT-Systemen ist QoS 0 für Telemetrie und QoS 1 für Befehle ein vernünftiger Ausgangspunkt.
Eine Retained Message speichert die letzte Nachricht unter einem Topic. Ein neu verbundener Subscriber erhält damit sofort den aktuellen Zustand, zum Beispiel .../state/online. Retain ist für Zustände sehr hilfreich, aber kein Ersatz für eine Datenbank und keine Historie. Für Temperaturverläufe braucht es weiterhin eine persistente Speicherung außerhalb des Brokers.
Für Geräteverfügbarkeit kann ein Client beim Verbindungsaufbau den Zustand online veröffentlichen und als Last Will eine retained Nachricht mit offline hinterlegen. Das schafft ein robustes Signal für Dashboards. Dabei sollte das Team festlegen, wie lange ein Zustand gültig ist und wie mit veralteten retained Nachrichten umzugehen ist.
Hosting und DevOps sicher betreiben
Ein MQTT-Broker kann auf einer kleinen virtuellen Maschine, in einem Container oder als verwalteter Dienst laufen. Die Topic-Struktur bleibt dabei dieselbe, aber Betriebsaufwand, Hochverfügbarkeit und Kosten unterscheiden sich deutlich.
Für einen einzelnen internen Dienst reicht oft eine dedizierte VM oder ein Container mit persistentem Speicher. Sobald mehrere Standorte, hohe Verbindungszahlen oder geschäftskritische Befehle hinzukommen, werden Clusterfähigkeit, Ausfallszenarien und Session-Persistenz wichtiger als die reine Nachrichtenrate.
- TLS aktivieren: Port 8883 ist ein üblicher Standard für verschlüsselte MQTT-Verbindungen. Port 1883 sollte höchstens in einem abgeschotteten Testnetz verwendet werden.
- ACLs nach Topic-Baum: Ein Gerät darf typischerweise nur unter seinem eigenen Gerätepfad veröffentlichen und gezielt notwendige Befehle abonnieren.
-
Keine globalen Rechte: Ein produktiver Client sollte nicht pauschal auf
#lesen oder auf beliebige Präfixe schreiben dürfen. - Konfiguration versionieren: Broker-Konfiguration, ACLs und Topic-Schema gehören in ein nachvollziehbares Deployment-Verfahren.
- Staging trennen: Test-Clients sollten niemals versehentlich retained Zustände oder Befehle im Produktionsbaum erzeugen können.
Für das Monitoring reichen Verbindungszähler allein nicht aus. Ich beobachte mindestens aktive Clients, Nachrichtenrate, Bytes pro Sekunde, fehlgeschlagene Authentifizierungen, Session-Warteschlangen und Zustellfehler. Viele Broker bieten dafür eigene System- oder Metrikkanäle an, doch diese sollten nicht die einzige Überwachungsquelle sein.
Lesen Sie auch: Website-Migration sicher planen und ohne SEO-Verluste umsetzen
Ein kleiner Testplan verhindert große Fehler
Vor dem Go-live sollte ein automatisierter Test prüfen, welcher Client welche Topics veröffentlichen und abonnieren darf. Dazu gehören mindestens ein erlaubter Zugriff, ein verweigerter Zugriff, die Wildcard-Grenzen und das Verhalten bei Broker-Neustart.
mosquitto_sub -t "prod/factory-01/device-017/#" -v
mosquitto_pub -t "prod/factory-01/device-017/state/online" -r -m "true"Besonders wichtig ist der Test auf versehentliche Überschneidungen. Ein Filter wie prod/factory-01/# kann weit mehr Daten erfassen als ursprünglich gedacht. In einer größeren Plattform lohnt sich deshalb eine kleine Schema-Prüfung, die Topic-Namen gegen erlaubte Ebenen, Präfixe und Versionen validiert.
Die wichtigste Entscheidung fällt vor dem ersten Publish
Ein MQTT-Topic ist klein, aber architektonisch weitreichend. Eine durchdachte Hierarchie erleichtert Routing, Berechtigungen, Monitoring und horizontale Skalierung, während nachträgliche Umbenennungen oft mehrere Clients, Dashboards und Datenpipelines gleichzeitig betreffen.
Mein pragmatischer Ansatz lautet: Umgebung und Mandant zuerst, Standort und Gerät danach, Nachrichtentyp am Ende. Dazu kommen klar definierte Regeln für Wildcards, QoS, retained Zustände und ACLs. Wer diese Entscheidungen als Teil des Deployments behandelt, bekommt einen Broker, der nicht nur Nachrichten transportiert, sondern auch im täglichen DevOps-Betrieb zuverlässig beherrschbar bleibt.