QoS 1 redelivery behavior

Following What is MQTT Quality of Service blog post, it states that for QoS 1:

If the sender doesn’t receive the PUBACK packet within a reasonable time frame, it re-transmits the message to ensure its delivery.

However, the MQTT 5 specification’s delivery retry section states:

When a Client reconnects with Clean Start set to 0 and a session is present, both the Client and Server MUST resend any unacknowledged PUBLISH packets (where QoS > 0) and PUBREL packets using their original Packet Identifiers. This is the only circumstance where a Client or Server is REQUIRED to resend messages. Clients and Servers MUST NOT resend messages at any other time

This information seems to be conflicting. I tested this functionality out with the HiveMQ MQTT Client library for Java (1.3.3) and noticed that even with manualAcknowledgement(true) when subscribing to topics, the functionality described in the MQTT 5 specification was correct on the behavior… messages were only re-delivered on reconnects. I waited up to 45 seconds for an unacknowledged message to be re-delivered and it did not happen.

How then does QoS 1 guarantee delivery at least one time, if a client has to literally disconnect and reconnect before any message re-delivery attempts are made by the sender?

Hi @dlowreytcna,

Thank you for bringing up this interesting question about QoS 1 redelivery behavior. I appreciate the detailed explanation of your observations and concerns.

You’ve highlighted an important nuance in the MQTT specification. Let me clarify:

  1. The specification allows for clients to re-publish QoS 1 packets if they don’t receive a PUBACK within a reasonable time.
  2. However, it doesn’t mandate that this re-publishing must occur within the same connection.
  3. What the specification does require is re-publishing of unacknowledged messages upon reconnection.

Based on your description, the HiveMQ MQTT Client library is indeed acting in accordance with the specification by re-publishing messages when you reconnect.

If you’re looking for more immediate redelivery attempts, you might need to implement this at the application level. You could program your client to wait a “reasonable time” after sending a PUBLISH packet, and then resend if no PUBACK was received within that time frame.

Does this help clarify the behavior you’re seeing? If you have any further questions, please don’t hesitate to ask.

Best regards,
Dasha from the HiveMQ Team