Explain MQTT QoS levels 0, 1, and 2 with tradeoffs.
MQTT defines three Quality of Service levels that control message delivery guarantees between a client and the broker.
QoS 0 ("at most once") — fire and forget. The sender publishes the message and does not wait for acknowledgment. The message may be lost if the network drops the packet. This is the fastest and lowest-overhead option: one packet, no state, no retransmission. Use QoS 0 for high-frequency sensor telemetry where losing an occasional reading is acceptable (e.g., temperature every 5 seconds — a missing sample is irrelevant because the next one arrives shortly).
QoS 1 ("at least once") — the sender stores the message and retransmits until the broker acknowledges receipt with a PUBACK. This guarantees delivery but may deliver the message more than once if the PUBACK is lost (the sender retransmits, the broker processes the duplicate). This is the most commonly used level — it provides reliable delivery with a simple two-packet handshake (PUBLISH + PUBACK). Your application must be idempotent (handle duplicate messages gracefully) or deduplicate using message IDs. Use QoS 1 for alerts, commands, and state changes.
QoS 2 ("exactly once") — a four-packet handshake (PUBLISH, PUBREC, PUBREL, PUBCOMP) guarantees the message is delivered exactly once with no duplicates. This is the most reliable but also the most expensive: it requires four packets, the broker must maintain state for each in-flight message, and both sides must store messages until the handshake completes. Use QoS 2 only when duplicates would cause real problems — financial transactions, billing events, or firmware update commands. In practice, most IoT systems use QoS 0 or QoS 1. Designing your application to tolerate duplicates (idempotency) is usually simpler and more efficient than using QoS 2.
Source: Networking Protocols Q&A
