Grundlagen

MQTT-QoS-Stufen erklärt: QoS 0, 1 und 2

MQTT QoS erklärt: wie QoS 0, 1 und 2 Paket für Paket funktionieren, was die Downgrade-Regel bedeutet, wie Sessions wirken und welche QoS-Stufe du wählst.

Aktualisiert · 7 Min. Lesezeit

MQTT QoS (Quality of Service) legt fest, wie viel Aufwand das Protokoll treibt, um eine Nachricht zuzustellen. Es gibt drei QoS-Stufen – 0, 1 und 2 –, und jede fügt Bestätigungspakete hinzu, um im Gegenzug eine stärkere Garantie zu bieten. Die richtige Stufe zu wählen ist eine der wichtigsten Designentscheidungen in einem MQTT-System: zu niedrig, und du verlierst Daten; zu hoch, und du verschwendest Bandbreite und Latenz.

QoS-Stufen im Überblick

QoSGarantiePakete pro HopDuplikate möglich?
0Höchstens einmal (at most once)1 (PUBLISH)Nein – aber Nachrichten können verloren gehen
1Mindestens einmal (at least once)2 (PUBLISH, PUBACK)Ja
2Genau einmal (exactly once)4 (PUBLISH, PUBREC, PUBREL, PUBCOMP)Nein

Ein wichtiges Detail: QoS wird pro Hop ausgehandelt. Die QoS des Publishers bestimmt den Weg zum Broker, die QoS der Subscription den Weg vom Broker zu jedem einzelnen Subscriber.

QoS 0 – höchstens einmal

Der Sender schickt das PUBLISH einmal ab und vergisst es dann. Es gibt keine Bestätigung und keinen Packet Identifier. Bricht die TCP-Verbindung ab, während die Nachricht unterwegs ist, ist sie weg.

Ablauf bei QoS 0
Sender                     Receiver
  | ---- PUBLISH (QoS 0) ---> |
  |                           |  (no reply)

QoS 0 ist die günstigste Option und völlig in Ordnung für hochfrequente Telemetrie – ein Temperaturwert pro Sekunde, eine GPS-Position, ein Heartbeat –, bei der die nächste Nachricht die verlorene ohnehin ersetzt. Beachte, dass TCP auf einer stehenden Verbindung weiterhin vor Datenfehlern und falscher Reihenfolge schützt; das Risiko besteht darin, Nachrichten bei Verbindungsabbrüchen zu verlieren.

QoS 1 – mindestens einmal

Der Sender vergibt einen Packet Identifier, speichert die Nachricht und wartet auf ein PUBACK mit derselben ID. Bis die Bestätigung eintrifft, gilt die Nachricht als „in flight“. Bricht die Verbindung vorher ab, sendet der Sender sie bei der Wiederaufnahme der Session mit gesetztem DUP-Flag erneut.

Ablauf bei QoS 1
Sender                          Receiver
  | ---- PUBLISH (QoS 1, id=7) ---> |  store + deliver
  | <--------- PUBACK (id=7) ------ |
  |  delete stored message          |

Der Haken: Geht das PUBACK verloren, hat der Empfänger die Nachricht schon verarbeitet und bekommt sie bei der erneuten Übertragung noch einmal. QoS 1 garantiert also die Zustellung, erlaubt aber Duplikate. Für die meisten Anwendungen ist das der richtige Kompromiss – mach deine Handler idempotent (zum Beispiel mit einer Message-ID oder einem Zeitstempel in der Payload), und du bekommst Zuverlässigkeit bei geringem Overhead.

QoS 2 – genau einmal

QoS 2 nutzt einen vierstufigen Handshake, damit keine Seite die Nachricht doppelt zustellen kann:

Ablauf bei QoS 2
Sender                          Receiver
  | ---- PUBLISH (QoS 2, id=9) ---> |  store id=9, (deliver)
  | <--------- PUBREC (id=9) ------ |
  | ---------- PUBREL (id=9) -----> |  release id=9
  | <--------- PUBCOMP (id=9) ----- |
  |  done                           |
  1. PUBLISH – der Sender überträgt die Nachricht und behält eine Kopie.
  2. PUBREC – der Empfänger bestätigt den Empfang und merkt sich den Packet Identifier. Jedes erneut gesendete PUBLISH mit dieser ID wird als Duplikat erkannt und nicht noch einmal zugestellt.
  3. PUBREL – der Sender verwirft die Nachricht und teilt dem Empfänger mit, dass er die ID freigeben darf.
  4. PUBCOMP – der Empfänger bestätigt; die ID kann wiederverwendet werden.

Der Preis sind zwei Round Trips pro Hop und Zustand auf beiden Seiten. QoS 2 lohnt sich für Nachrichten, bei denen ein Duplikat tatsächlich Schaden anrichtet und sich nicht in der Anwendung herausfiltern lässt – etwa Abrechnungsereignisse oder einmalige Aktorbefehle. In der Praxis setzen viele Teams stattdessen auf QoS 1 plus Deduplizierung.

Die Downgrade-Regel: effektive QoS

Ein Subscriber fordert in seinem SUBSCRIBE-Paket eine maximale QoS an, und der Broker meldet die gewährte QoS im SUBACK zurück. Jede Nachricht wird dann mit der niedrigeren der beiden Stufen zugestellt – Publish-QoS oder gewährte Subscription-QoS:

Gepublisht mitAbonniert mitZugestellt mit
QoS 2QoS 0QoS 0
QoS 1QoS 2QoS 1
QoS 0QoS 1QoS 0
QoS 2QoS 2QoS 2

Broker können die QoS außerdem begrenzen: In MQTT 5 kann ein Broker im CONNACK ein Maximum QoS ankündigen, und manche Broker oder Cloud-Dienste unterstützen QoS 2 überhaupt nicht. Prüfe immer die gewährte QoS im SUBACK, statt anzunehmen, dass du bekommen hast, was du angefragt hast.

QoS und Sessions: Was offline passiert

QoS schützt Nachrichten nur, solange eine Session existiert. Bei einer Clean Session (cleanSession=true in 3.1.1, cleanStart=true mit einer Session Expiry von 0 in MQTT 5) verwirft der Broker Subscriptions und ausstehende Nachrichten, sobald sich der Client trennt – QoS-1- und QoS-2-Nachrichten, die gepublisht werden, während du offline bist, werden dir also schlicht nie zugestellt.

Damit ein Client Nachrichten erhält, die eintreffen, während er offline ist, brauchst du alle drei Punkte:

  • eine stabile, eindeutige Client-ID,
  • eine persistente Session (cleanSession=false bzw. in MQTT 5 ein Session Expiry Interval ungleich null),
  • eine Subscription mit QoS 1 oder 2 und Nachrichten, die mit QoS 1 oder 2 gepublisht werden.

Beachte außerdem, dass unbestätigte Nachrichten erst dann erneut gesendet werden, wenn die Session nach einem Reconnect wieder aufgenommen wird – weder 3.1.1 noch 5.0 verlangen ein erneutes Senden auf einer stehenden Verbindung, weil TCP dort Verluste bereits abfängt.

QoS in der Praxis testen

Mit der Mosquitto-CLI kannst du QoS live beobachten. Das Flag -d gibt jedes Paket aus, sodass du PUBREC/PUBREL/PUBCOMP vorbeiziehen siehst:

bash
# subscriber with a persistent session (-c) and fixed client ID
mosquitto_sub -h broker.emqx.io -t 'testmqtt/qos-demo/#' -q 2 -c -i qos-demo-sub -d

# publish at QoS 2
mosquitto_pub -h broker.emqx.io -t 'testmqtt/qos-demo/order' -m 'order-1001' -q 2 -d

Stoppe den Subscriber, publishe ein paar QoS-1-Nachrichten und starte ihn dann mit derselben Client-ID neu: Die zwischengespeicherten Nachrichten sollten ankommen. Im Browser kannst du im Online-MQTT-Client die QoS pro Subscription und pro Publish wählen. Weitere Testszenarien findest du unter MQTT-Broker testen.

Im Online-MQTT-Client ausprobieren

Die passende QoS-Stufe wählen

  • QoS 0 – häufige Sensordaten, Positionen, Metriken, bei denen nur der letzte Wert zählt.
  • QoS 1 – der sinnvolle Standard für Events, Alarme und Befehle; kombiniere ihn mit idempotenten Handlern.
  • QoS 2 – seltene Fälle, in denen Duplikate teuer sind und sich nachgelagert nicht deduplizieren lassen.

QoS arbeitet Hand in Hand mit Retained Messages und Last Will; wenn du neu im Protokoll bist, fang mit Was ist MQTT? an.

Häufig gestellte Fragen

Welche MQTT-QoS-Stufe sollte ich verwenden?

Nutze QoS 0 für häufige Telemetrie, bei der ein verlorener Messwert keine Rolle spielt, QoS 1 für die meisten Events und Befehle (und mach deine Handler idempotent) und QoS 2 nur dann, wenn Duplikate wirklich schaden und du sie in der Anwendung nicht deduplizieren kannst.

Warum habe ich eine QoS-1-Nachricht zweimal erhalten?

QoS 1 bedeutet Zustellung mindestens einmal. Geht die Bestätigung verloren – typischerweise, weil die Verbindung abgebrochen ist –, sendet der Sender die Nachricht nach dem Reconnect mit gesetztem DUP-Flag erneut, sodass der Empfänger sie doppelt sehen kann.

Garantiert QoS 2 eine Ende-zu-Ende-Zustellung genau einmal?

Nein. QoS gilt für jeden Hop separat: Publisher zu Broker und Broker zu Subscriber. Der Subscriber erhält das Minimum aus Publish-QoS und Subscription-QoS, und Nachrichten für Offline-Clients werden nur aufbewahrt, wenn diese eine persistente Session haben.