MQTT Essentials Part 6: Quality of Service 0, 1 & 2
Welcome to the sixth part of the MQTT Essentials, a blog series about the core features and concepts in the MQTT protocol. In this post we’ll focus on the different Quality of Service levels within MQTT. We already stumbled upon the term ‘quality of service’ a few times in some of the previous posts, so now is the time to explain what’s behind it.
Quality of Service
What is Quality of Service?
The Quality of Service (QoS) level is an agreement between sender and receiver of a message regarding the guarantees of delivering a message. There are 3 QoS levels in MQTT:
- At most once (0)
- At least once (1)
- Exactly once (2).
When talking about QoS there are always two different parts of delivering a message: publishing client to broker and broker to subscribing client. We need to look at them separately since there are subtle differences. The QoS level for publishing client to broker is depending on the QoS level the client sets for the particular message. When the broker transfers a message to a subscribing client it uses the QoS of the subscription made by the client earlier. That means, QoS guarantees can get downgraded for a particular receiving client if subscribed with a lower QoS.
Why is Quality of Service important?
QoS is a major feature of MQTT, it makes communication in unreliable networks a lot easier because the protocol handles retransmission and guarantees the delivery of the message, regardless how unreliable the underlying transport is. Also it empowers a client to choose the QoS level depending on its network reliability and application logic.
How does it work?
So how is the quality of service implemented in the MQTT protocol ? We will look at each level one by one and explain the functionality.
QoS 0 – at most once
The minimal level is zero and it guarantees a best effort delivery. A message won’t be acknowledged by the receiver or stored and redelivered by the sender. This is often called “fire and forget” and provides the same guarantee as the underlying TCP protocol.
QoS 1 – at least once
When using QoS level 1, it is guaranteed that a message will be delivered at least once to the receiver. But the message can also be delivered more than once.
The sender will store the message until it gets an acknowledgement in form of a PUBACK command message from the receiver.
The association of PUBLISH and PUBACK is done by comparing the packet identifier in each packet. If the PUBACK isn’t received in a reasonable amount of time the sender will resend the PUBLISH message. If a receiver gets a message with QoS 1, it can process it immediately, for example sending it to all subscribing clients in case of a broker and then replying with the PUBACK.
The duplicate (DUP) flag, which is set in the case a PUBLISH is redelivered, is only for internal purposes and won’t be processed by broker or client in the case of QoS 1. The receiver will send a PUBACK regardless of the DUP flag.
The highest QoS is 2, it guarantees that each message is received only once by the counterpart. It is the safest and also the slowest quality of service level. The guarantee is provided by two flows there and back between sender and receiver.
If a receiver gets a QoS 2 PUBLISH it will process the publish message accordingly and acknowledge it to the sender with a PUBREC message.
The receiver will store a reference to the packet identifier until it has send the PUBCOMP. This is important for avoid processing the message a second time. When the sender receives the PUBREC it can safely discard the initial publish, because it knows that the counter part has successfully received the message. It will store the PUBREC and respond with a PUBREL.
After the receiver gets the PUBREL it can discard every stored state and answer with a PUBCOMP. The same is true when the sender receives the PUBCOMP.
When the flow is completed both parties can be sure that the message has been delivered and the sender also knows about it.
Whenever a packet gets lost on the way, the sender is responsible for resending the last message after a reasonable amount of time. This is true when the sender is a MQTT client and also when a MQTT broker sends a message. The receiver has the responsibility to respond to each command message accordingly.
Good to know
There are a few things you should have in mind when using QoS. These are not obvious or clear on first sight.
Downgrade of QoS
As already said, the QoS flows between a publishing and subscribing client are two different things as well as the QoS can be different. That means the QoS level can be different from client A, who publishes a message, and client B, who receives the published message. Between the sender and the broker the QoS is defined by the sender. When the broker sends out the message to all subscribers, the QoS of the subscription from client B is used. If client B has subscribed to the broker with QoS 1 and client A sends a QoS 2 message, it will be received by client B with QoS 1. And of course it could be delivered more than once to client B, because QoS 1 only guarantees to deliver the message at least once.
Packet identifiers are unique per client
Also important to know is that each packet identifier (used for QoS 1 and QoS 2) is unique between one client and a broker and not between all clients. If a flow is completed the same packet identifier can be reused anytime. That’s also the reason why the packet identifier doesn’t need to be bigger than 65535, because it is unrealistic that a client sends a such large number of message, without completing the flow.
We are often asked, when to choose which QoS level. The following should provide you some guidance if you are also confronted with this decision. Often this is heavily depending on your use case.
Use QoS 0 when …
- You have a complete or almost stable connection between sender and receiver. A classic use case is when connecting a test client or a front end application to a MQTT broker over a wired connection.
- You don’t care if one or more messages are lost once a while. That is sometimes the case if the data is not that important or will be send at short intervals, where it is okay that messages might get lost.
- You don’t need any message queuing. Messages are only queued for disconnected clients if they have QoS 1 or 2 and a persistent session.
Use QoS 1 when …
- You need to get every message and your use case can handle duplicates. The most often used QoS is level 1, because it guarantees the message arrives at least once. Of course your application must be tolerating duplicates and process them accordingly.
- You can’t bear the overhead of QoS 2. Of course QoS 1 is a lot faster in delivering messages without the guarantee of level 2.
Use QoS 2 when …
- It is critical to your application to receive all messages exactly once. This is often the case if a duplicate delivery would do harm to application users or subscribing clients. You should be aware of the overhead and that it takes a bit longer to complete the QoS 2 flow.
Queuing of QoS 1 and 2 messages
All messages sent with QoS 1 and 2 will also be queued for offline clients, until they are available again. But queuing is only happening, if the client has a persistent session.
So that’s the end of part six in our MQTT Essentials series. We hope you enjoyed it. In the next post we’ll cover persistent sessions in MQTT, which are tied up closely with Quality of Service levels.
Have a great week and we’ll hope to see you on the next MQTT Monday!
You like the MQTT Essentials? Then sign up for our newsletter and get notified on each new post as soon as its available. If you prefer RSS, you can subscribe to our RSS feed here.