QoS levels
How CloudSignal leverages MQTT's built-in delivery guarantees to ensure your messages arrive - and how to choose the right level for your use case.
Message deliverability is not something you should have to build yourself. Most custom messaging implementations start with a simple WebSocket push and then spend months bolting on retry logic, acknowledgment tracking, deduplication, and persistence - reinventing what MQTT solved at the protocol level decades ago.
CloudSignal gives you these guarantees out of the box through MQTT's three Quality of Service levels. You choose the delivery guarantee per message, and the broker handles the rest.
The three levels
QoS 0 - at most once (fire and forget)
The sender publishes once. No acknowledgment, no retry. The broker delivers on a best-effort basis.
Characteristics:
- Single packet per message - lowest overhead
- No acknowledgment from broker or subscriber
- Messages may be lost during network interruptions
- Lowest latency of all QoS levels
Use when: Data arrives frequently and a missed reading is quickly replaced. Cursor positions in a collaborative editor, live presence updates, AI token streaming, live stock tickers - anywhere freshness matters more than completeness.
QoS 1 - at least once
The sender publishes and waits for an acknowledgment (PUBACK). If no PUBACK arrives, the sender retransmits until acknowledged.
Characteristics:
- Broker acknowledges receipt before delivering
- Sender retries automatically if acknowledgment is lost
- Guaranteed delivery - the message will arrive
- Duplicates are possible - if the ack is lost, the sender retransmits and the subscriber may receive the same message twice
- Two packets per message (moderate overhead)
Use when: Every message should arrive, and your application can handle or deduplicate repeated deliveries. Notifications, event logs, alert systems, chat messages - cases where missing a message is worse than processing one twice.
QoS 2 - exactly once
A four-step handshake ensures each message is delivered exactly one time. No duplicates, no loss.
Characteristics:
- Four-packet handshake per message - highest overhead
- No duplicates and no loss - the strongest guarantee
- Higher latency due to the full handshake
- Uses more broker resources per message
Use when: Duplicate processing would cause real problems. Billing events, actuator commands on physical equipment, configuration deployments, financial transactions - operations where executing twice would be incorrect or dangerous.
Side-by-side comparison
| QoS 0 | QoS 1 | QoS 2 | |
|---|---|---|---|
| Guarantee | At most once | At least once | Exactly once |
| Message loss | Possible | No | No |
| Duplicates | No | Possible | No |
| Packets per message | 1 | 2 | 4 |
| Overhead | Lowest | Moderate | Highest |
| Latency | Lowest | Low | Higher |
| Broker resources | Minimal | Moderate | Highest |
How QoS works across two hops
An important detail: QoS applies independently on each half of the message path.
The broker respects the lower of the published QoS and the subscriber's requested QoS. If you publish at QoS 2 but a subscriber requested QoS 1, that subscriber receives the message at QoS 1.
This means:
- Publishers control the upper bound of delivery reliability
- Subscribers can downgrade the QoS for their own consumption
- The broker never upgrades a message beyond what was published
This two-hop model lets resource-constrained subscribers (like battery-powered devices) request QoS 0 even when publishers use QoS 1 or 2. Each client chooses the guarantee level that fits its capabilities.
Why protocol-level guarantees matter
Building delivery guarantees in application code means implementing:
- Message persistence and retry queues
- Acknowledgment tracking with timeouts
- Deduplication logic (message IDs, idempotency keys)
- Ordered delivery after retransmission
- Cleanup of in-flight message state
Every team that builds messaging from scratch re-implements these mechanisms - and each implementation has its own edge cases and failure modes.
MQTT standardized this in 1999. CloudSignal's broker has been handling these guarantees at the protocol level across millions of messages. When you set qos: 1 on a publish call, you get at-least-once delivery without writing a single line of retry logic.
Choosing the right level
Start with QoS 0 and increase only when your use case requires it.
Choose QoS 0 when:
- Data arrives frequently and stale readings are replaced quickly
- Low latency is the priority
- You are bandwidth- or battery-constrained
Choose QoS 1 when:
- Every message must arrive, but duplicates are tolerable
- You are building notification, alerting, or event-logging systems
- You want reliability without the overhead of exactly-once
Choose QoS 2 when:
- Duplicate processing would cause errors (billing, commands, state transitions)
- The cost of a missed or repeated message is high
- You can accept additional latency for the strongest guarantee
QoS 2 uses four times the packets of QoS 0. For high-throughput scenarios (thousands of messages per second), this overhead adds up. Use QoS 2 selectively for messages that truly require it, not as a default.
Next steps
- QoS in depth - Protocol-level walkthrough with packet-by-packet examples
- Offline & Retain - How QoS interacts with offline queuing and retained messages
Pub/Sub & topics
How CloudSignal uses MQTT's topic-based publish/subscribe model - with wildcards, shared subscriptions, and ACL enforcement - to route messages exactly where they need to go.
Offline & Retain
How CloudSignal's MQTT infrastructure handles offline message queuing and retained messages - built into the protocol, no extra systems required.