← All Posts

MQTT QoS Levels Explained: When to Use QoS 0, 1, or 2

MQTT QoS (Quality of Service) is the delivery guarantee for a message: QoS 0 is at most once (no acknowledgment, can be lost), QoS 1 is at least once (acknowledged with PUBACK, duplicates possible), and QoS 2 is exactly once (four-packet handshake, no duplicates). The publisher sets a QoS per message, the subscriber sets one per subscription, and the broker delivers at the lower of the two. Pick QoS 0 for readings that are replaced by the next one, QoS 1 for alarms and commands, and QoS 2 only where a duplicate does real harm.

Choosing the wrong level causes either lost messages or unnecessary network overhead. Whether you are setting up a local broker for device testing or building an industrial IoT pipeline, here is how each level works and when to use it.

How MQTT QoS Works

QoS is negotiated between the sender (publisher or broker) and the receiver (subscriber or broker). Each message has a QoS level set by the publisher. The broker delivers the message to subscribers at the subscribed QoS level or lower: the lower of the two wins. This means if you publish at QoS 2 but a subscriber subscribed at QoS 0, the broker delivers at QoS 0.

There are two delivery hops in MQTT:

  1. Publisher → Broker: The publisher sends the message to the broker at the specified QoS.
  2. Broker → Subscriber: The broker forwards the message to each subscriber at the subscribed QoS (or the published QoS, whichever is lower).

Each hop is independent. A message published at QoS 2 might be delivered to one subscriber at QoS 2 and to another at QoS 0, depending on their subscription levels.

QoS 0: At Most Once

The publisher sends the message once. No acknowledgment. No retry. If the network drops the packet, the message is lost, and the sender keeps no copy to retransmit.

Flow

Publisher sends PUBLISH → Broker receives and forwards → Done. Fire and forget.

When to Use QoS 0

  • Sensor data that is updated frequently. Temperature readings every 5 seconds, ambient light levels, humidity. If one reading is lost, the next one arrives 5 seconds later. No harm done.
  • High-frequency telemetry. GPS coordinates from a fleet tracker updating at 1 Hz. One missed position update is irrelevant: the next one corrects it immediately.
  • Status broadcasts. "I am alive" heartbeat messages. The next heartbeat in 30 seconds renders the lost one irrelevant.
  • Bandwidth-constrained networks. On satellite links or low-bandwidth cellular connections, QoS 0 minimizes overhead: no ACK packets, no retransmissions.

QoS 1: At Least Once

The publisher sends the message and waits for a PUBACK from the broker. If the acknowledgment never arrives, the publisher sends the message again with the DUP flag set. The MQTT spec requires this retransmission when a client reconnects with a persistent session, and many client libraries also retry on a timeout. This guarantees delivery, but the message might arrive more than once.

Flow

Publisher sends PUBLISH (Packet ID: 42) → Broker receives, stores, sends PUBACK (42) → Publisher receives PUBACK → Done. If PUBACK is lost, publisher resends PUBLISH with the same Packet ID and the DUP flag set. The broker may deliver both copies to subscribers.

The Duplicate Problem

QoS 1 guarantees at least once delivery, which means duplicates are possible. Your application must handle this. Common strategies:

  • Idempotent operations: "Set temperature to 22°C" is idempotent: receiving it twice has the same effect as once.
  • Timestamp-based deduplication: Ignore messages with timestamps older than the last processed message.
  • Sequence numbers: Track the last sequence number processed and ignore any that are not strictly increasing.

When to Use QoS 1

  • Alarm and event notifications. "Motor overload detected" or "Tank level below threshold": these must be delivered. A duplicate alarm is annoying but not harmful.
  • Configuration commands. "Set setpoint to 75.0": duplicates are harmless for idempotent values.
  • Data you cannot afford to lose. Production counts, batch records and other values that are not simply replaced by the next reading. QoS 1 delivers them with modest overhead as long as your application tolerates the occasional duplicate.

QoS 2: Exactly Once

QoS 2 uses a four-part handshake so that the message is delivered exactly once on each hop: no duplicates, no losses, as long as the session state survives. This is the most reliable and most expensive QoS level.

Flow

Publisher sends PUBLISH (Packet ID: 42) → Broker receives, sends PUBREC (42) → Publisher sends PUBREL (42) → Broker sends PUBCOMP (42) → Done. The broker forwards the message to subscribers either when the PUBLISH arrives or when the PUBREL arrives: MQTT 3.1.1 leaves that choice to the implementation, and MQTT 5.0 shows forwarding on the PUBLISH.

The Overhead Cost

QoS 2 requires four packets for every message (PUBLISH, PUBREC, PUBREL, PUBCOMP) compared to one for QoS 0 and two for QoS 1. That is twice the packets of QoS 1 and four times those of QoS 0, plus an extra round trip of latency. How much that costs in throughput depends on the network and the broker.

When to Use QoS 2

  • Billing and metering data. Energy readings that feed invoices are a common reason to pick QoS 2, because a duplicate would be counted twice. A timestamp or sequence number in the payload lets you deduplicate QoS 1 deliveries instead, and QoS 2 does not protect you if the session is lost, for example after a reconnect with a clean session.
  • Financial transactions. Payment confirmations, order submissions, trade executions. Duplicates can have monetary consequences, so many designs use QoS 2 here or add an application-level transaction ID.
  • Not for safety functions. MQTT QoS is a delivery guarantee between MQTT peers, not a safety mechanism. Emergency stops and other safety functions belong on hardwired or certified safety circuits, not on an MQTT topic.

Quick Comparison

FactorQoS 0QoS 1QoS 2
DeliveryAt most onceAt least onceExactly once
Duplicates possibleNoYesNo
Packets per message124
AcknowledgmentNonePUBACKPUBREC, PUBREL, PUBCOMP
Typical useTelemetry, heartbeatsAlarms, commands, data you cannot loseMetering, transactions where a duplicate costs money

QoS 2 adds exactly-once delivery at the cost of 4 packets per message. Reserve it for scenarios where duplicates have real consequences.

Retained Messages and Last Will

Two MQTT features interact with QoS:

  • Retained messages: The broker stores the last message published on a topic with the retain flag set. New subscribers receive this stored message immediately upon subscribing. Useful for "last known good" state: current temperature, latest setpoint, connection status. The retained message uses the QoS it was published with.
  • Last Will and Testament (LWT): The broker publishes a pre-configured message if a client disconnects ungracefully. The LWT message has its own QoS level and retain flag. For "device offline" notifications, QoS 1 makes delivery to subscribers more reliable even if the network is unstable at the moment of disconnection.
Practical advice: Default to QoS 1 for data that must arrive. Use QoS 0 for high-frequency telemetry where the next reading replaces a lost one. Use QoS 2 only where a duplicate costs money and you cannot deduplicate in the application.

MQTT Explorer for macOS

MacTools MQTT Explorer: built-in broker, publish/subscribe, topic tree browser, message history. QoS 0, 1, and 2 all supported. No Homebrew, no CLI. $29.99 one-time.

Get MacTools MQTT Explorer

Related: Full SCADA System

Need continuous MQTT monitoring with dashboards, alarms, and trending? Voltrus SCADA supports Modbus, OPC-UA, Siemens S7, EtherNet/IP, DNP3, BACnet and MQTT. The core is free and open source (AGPL-3.0).

Further Reading