Delivery and store-and-forward

What is an acknowledgment (ACK)?

An acknowledgment (ACK) is a short message a receiver sends back to confirm that it got something. The sender keeps its copy and retransmits after a timeout until an ACK arrives, which is how protocols build reliable delivery on top of links that lose data. An ACK only confirms what the protocol says it confirms, usually receipt, not that the receiving application has acted on the message.

Learning objectives

After reading this article you will be able to:

  • Describe how acknowledgments, timeouts and retransmission build reliable delivery
  • Distinguish per-message, cumulative, hop-by-hop and end-to-end acknowledgments
  • Explain why a lost acknowledgment produces a duplicate message

The basic loop

Every acknowledgment scheme follows the same loop. The sender transmits a message, keeps a copy, and starts a timer. If an ACK comes back before the timer runs out, the sender can discard its copy and move on. If the timer runs out first, the sender assumes the message or its ACK was lost and sends the message again.

The Constrained Application Protocol (CoAP, RFC 7252), designed for constrained devices and lossy networks, shows the loop in its simplest form. A message marked Confirmable must be answered with an Acknowledgement that echoes its Message ID. The sender’s first timeout is a random value between ACK_TIMEOUT and ACK_TIMEOUT multiplied by ACK_RANDOM_FACTOR, whose defaults are 2 seconds and 1.5. Each time the timeout fires the sender retransmits and doubles the timeout, until it has retransmitted MAX_RETRANSMIT times (default 4). Then it gives up and tells the application the send failed.

That doubling is a form of exponential backoff. It stops a sender from flooding a link that is already struggling.

Choosing the timeout

If the timeout is too short, the sender retransmits messages that were only slow, wasting capacity. If it is too long, real losses take a long time to repair. TCP solves this by measuring round-trip times and computing its retransmission timeout from them. RFC 6298 says that before any measurement the timeout should start at 1 second, and that each time the timer expires the sender must double it.

RFC 6298 also requires Karn’s algorithm: round-trip samples must not be taken from retransmitted segments, because when an ACK arrives for a message sent twice, there is no way to tell which copy it answers.

Per-message and cumulative ACKs

Protocols differ in what an ACK refers to.

  • Per-message ACKs name the message they confirm. CoAP echoes the Message ID, and MQTT’s PUBACK carries the Packet Identifier of the PUBLISH it answers.
  • Cumulative ACKs confirm everything up to a point. In TCP every byte has a sequence number, and an acknowledgment of sequence number X means all bytes before X have arrived. RFC 9293 notes that this makes duplicate detection straightforward when data is retransmitted.

To save traffic, a receiver may hold back an ACK briefly and confirm several segments with one. TCP calls this a delayed ACK and RFC 9293 limits the delay to less than 0.5 seconds.

Lost ACKs cause duplicates

An ACK can be lost just as easily as the message it confirms. When that happens the receiver has the message but the sender does not know it, so the sender sends it again. The receiver now sees a second copy.

Protocols handle this explicitly. RFC 7252 says a CoAP receiver should acknowledge every duplicate of a Confirmable message but process its content only once. SMTP’s specification warns that a receiving mail server must reply quickly at the end of a message to avoid duplicate messages caused by timeouts. Any system that retries on a missing ACK is giving at-least-once delivery and needs message deduplication at the receiver if duplicates matter.

Hop by hop or end to end

In a multi-hop network, an ACK can come from the next hop or from the final recipient. A hop-by-hop ACK tells the sender the neighbour has the message and the sender may free its copy. An end-to-end ACK tells it the recipient has it. RFC 4838 offers both in delay-tolerant networks: end-to-end acknowledgments that applications can use, and custody signals passed from one custodian to the next as responsibility moves along the path. A hop-by-hop ACK says nothing about whether later hops succeeded.

What an ACK does not prove

An ACK means exactly what its protocol defines, and that is usually less than “the work is done”. In MQTT 5.0, a QoS 1 receiver sends PUBACK once it has accepted ownership of the message, and the specification notes that it does not need to finish delivering the message onward first.

The same gap exists between devices. Offline Protocol’s local handoff guide treats delivery and acceptance as separate states. The mesh SDK’s message_delivered event means the message reached the other device, but the receiving app may not have stored it yet. So the receiving app commits the record locally and only then sends its own application receipt, and the sender treats only that receipt as acceptance. For anything that matters, decide which confirmation your app is waiting for, and show users the one they actually have.

Frequently asked questions

What is a negative acknowledgment (NACK)?

It is a reply that says something was not received or was rejected, so the sender can react without waiting for a timeout. CoAP's Reset message plays this role for a Confirmable message the receiver cannot process.

Sources

Build it with Offline Protocol

The Offline Protocol events reference describes the delivery outcomes the mesh SDK reports, including which events settle a send and which mean it is still pending.

Read the events reference