Quality of Service 0,1 & 2 - MQTT Essentials: Part 6

Written by The HiveMQ Team

Category: MQTT Essentials

Published: February 16, 2015




Welcome to part 6 of MQTT Essentials. A ten-part blog series on the core features and concepts of the MQTT protocol. In this post, we explain the different Quality of Service levels in MQTT. The term ‘quality of service’ has come up a few times in previous posts, let’s look into exactly what this term means.

Quality of Service

What is Quality of Service?

The Quality of Service (QoS) level is an agreement between the sender of a message and the receiver of a message that defines the guarantee of delivery for a specific message. There are 3 QoS levels in MQTT:

  • At most once (0)
  • At least once (1)
  • Exactly once (2).

When you talk about QoS in MQTT, you need to consider the two sides of message delivery:

  1. Message delivery form the publishing client to the broker.
  2. Message delivery from the broker to the subscribing client.

We will look at the two sides of the message delivery separately because there are subtle differences between the two. The client that publishes the message to the broker defines the QoS level of the message when it sends the message to the broker. The broker transmits this message to subscribing clients using the QoS level that each subscribing client defines during the subscription process. If the subscribing client defines a lower QoS than the publishing client, the broker transmits the message with the lower quality of service.

Why is Quality of Service important?

QoS is a key feature of the MQTT protocol. QoS gives the client the power to choose a level of service that matches its network reliability and application logic. Because MQTT manages the re-transmission of messages and guarantees delivery (even when the underlying transport is not reliable), QoS makes communication in unreliable networks a lot easier.

How does it work?

Let’s take a closer look at how each QoS level is implemented in the MQTT protocol and how it functions:

QoS 0 - at most once

The minimal QoS level is zero. This service level guarantees a best-effort delivery. There is no guarantee of delivery. The recipient does not acknowledge receipt of the message and the message is not stored and re-transmitted by the sender. QoS level 0 is often called “fire and forget” and provides the same guarantee as the underlying TCP protocol.

publish_qos0_flow

QoS 1 - at least once

QoS level 1 guarantees that a message is delivered at least one time to the receiver. The sender stores the message until it gets a  PUBACK packet from the receiver that acknowledges receipt of the message. It is possible for a message to be sent or delivered multiple times.

publish_qos1_flow

puback_packet

The sender uses the packet identifier in each packet to match the PUBLISH packet to the corresponding PUBACK packet. If the sender does not receive a PUBACK packet in a reasonable amount of time, the sender resends the PUBLISH packet. When a receiver gets a message with QoS 1, it can process it immediately. For example, if the receiver is a broker, the broker sends the message to all subscribing clients and then replies with a PUBACK packet. If the publishing client sends the message again it sets a duplicate (DUP) flag. In QoS 1, this DUP flag is only used for internal purposes and is not processed by broker or client. The receiver of the message sends a PUBACK, regardless of the DUP flag. 

QoS 2 - exactly once

QoS 2 is the highest level of service in MQTT. This level guarantees that each message is received only once by the intended recipients. QoS 2 is the safest and slowest quality of service level. The guarantee is provided by at least two request/response flows (a four-part handshake) between the sender and the receiver. The sender and receiver use the packet identifier of the original PUBLISH message to coordinate delivery of the message.

publish_qos2_flow

When a receiver gets a QoS 2 PUBLISH packet from a sender, it processes the publish message accordingly and replies to the sender with a PUBREC packet that acknowledges the PUBLISH packet. If the sender does not get a PUBREC packet from the receiver, it sends the PUBLISH packet again with a duplicate (DUP) flag until it receives an acknowledgement. 

pubrec_packet

Once the sender receives a PUBREC packet from the receiver, the sender can safely discard the initial PUBLISH packet. The sender stores the PUBREC packet from the receiver and responds with a  PUBREL packet.

pubrel_packet

After the receiver gets the PUBREL packet, it can discard all stored states and answer with a PUBCOMP packet (the same is true when the sender receives the PUBCOMP). Until the receiver completes processing and sends the PUBCOMP packet back to the sender, the receiver stores a reference to the packet identifier of the original PUBLISH packet. This step is important to avoid processing the message a second time. After the sender receives the PUBCOMP packet, the packet identifier of the published message becomes available for reuse.

pubcomp_packet

When the QoS 2 flow is complete, both parties are sure that the message is delivered and the sender has confirmation of the delivery..

If a packet gets lost along the way, the sender is responsible to retransmit the message within a reasonable amount of time. This is equally true if the sender is an MQTT client or an MQTT broker. The recipient has the responsibility to respond to each command message accordingly.

Good to know

Some aspects of QoS are not very obvious at first glance. Here are a few things to keep in mind when you use QoS:

Downgrade of QoS

As we already mentioned, the QoS definition and levels between the client that sends (publishes) the message and the client that receives the message are two different things. The QoS levels of these two interactions can also be different. The client that sends  the PUBLISH message to the broker defines the QoS of the message. However, when the broker delivers the message to recipients (subscribers), the broker uses the QoS that the receiver (subscriber) defined during subscription. For example, client A is the sender of the message. Client B is the receiver of the message. If client B subscribes to the broker with QoS 1 and client A sends the message to the broker with QoS 2, the broker delivers the message to client B (receiver/subscriber) with QoS 1. The message can be delivered more than once to client B, because QoS 1 guarantees delivery of the message at least one time and does not prevent multiple deliveries of the same message.

Packet identifiers are unique per client

The packet identifier that MQTT uses for QoS 1 and QoS 2 is unique between a specific client and a broker within an interaction. This identifier is not unique between all clients. Once the flow is complete, the packet identifier is available for reuse. This reuse is the reason why the packet identifier does not need to exceed  65535. It is unrealistic that a client can send more than this number of messages without completing an interaction.

Best Practice

We are often asked for advice about how to choose the correct QoS level. Here are some guidelines that can help you in your decision making process. The QoS that is right for you depends heavily on your use case.

Use QoS 0 when …

  • You have a completely or mostly stable connection between sender and receiver. A classic use case for QoS 0 is connecting a test client or a front end application to an MQTT broker over a wired connection.
  • You don’t mind if a few messages are lost occasionally. The loss of some messages can be acceptable if the data is not that important or when data is sent at short intervals
  • You don’t need 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. QoS level 1 is the most frequently used service level because it guarantees the message arrives at least once but allows for multiple deliveries. Of course, your application must tolerate duplicates and be able to process them accordingly.
  • You can’t bear the overhead of QoS 2. QoS 1 delivers messages much faster than QoS 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 can harm application users or subscribing clients. Be aware of the overhead and that the QoS 2 interaction takes more time to complete.

Queuing of QoS 1 and 2 messages

All messages sent with QoS 1 and 2 are queued for offline clients until the client is available again. However, this queuing is only possible if the client has a persistent session.


That’s the end of part six in our MQTT Essentials series. We hope that you find this information useful. In the next post we’ll cover a subject that is closely associated with Quality of Service levels: persistent sessions in MQTT.

Have a great week and we look forward to seeing you for the next MQTT Monday!

Are you enjoying the MQTT Essentials? Then sign up for our newsletter and get notified about each new post as soon as its available. If you prefer RSS, you can subscribe to our RSS feed here.

About The HiveMQ Team

We love writing about MQTT, IoT protocols and architecture in general. Our experts are here to help, so reach out to us if we can help!
Contact us
<  HiveMQ 2.0.2 released - Important Bugfix Upgrade   |   Persistent Session and Queuing Messages - MQTT Essentials: Part 7   >