6  CoAP Exchange Reliability Contracts

coap
message-types
reliability
exchanges

6.1 Start With the Lost ACK

A Confirmable command can be delivered, executed, and still look failed if the ACK disappears on the way back. The client retries; the server must recognize the duplicate; the response still needs to match the original request instead of running the command twice.

This contract page follows that failure path. It separates Message ID, Token, timers, duplicate suppression, piggybacked responses, separate responses, and Reset so a trace review can prove what happened.

6.2 Learning Objectives

After this page, you should be able to:

  • Separate CoAP message-layer type from request/response Code and Token semantics in a packet trace.
  • Set CON/NON policy and document ACK timeout, randomization, backoff, and retransmission evidence.
  • Distinguish piggybacked ACK-plus-response exchanges from separate responses that use a new Message ID.
  • Diagnose duplicate suppression, Message ID reuse, Token correlation, and RST paths after context loss.

6.3 Why This Contract Comes After Message Types

CoAP Message Types introduces CON, NON, ACK, and RST as the four exchange types used by constrained devices. This page narrows in on the reliability contract behind those labels: which layer a field belongs to, how long a sender waits before retrying, how a delayed response is matched to its request, and how a server avoids executing the same Confirmable request twice.

The CoAP message story remains two-layered: Message ID proves delivery behavior, while Token and Code prove the request/response relationship.

Use it when you are reviewing traces, sizing retry windows for sleepy devices, deciding which messages are allowed to be NON, or debugging why a rebooted endpoint answers with Reset instead of a normal acknowledgment.

Overview: Four Message Types Living in Two Layers

CoAP (RFC 7252) splits every exchange into two layers. The messaging layer handles the datagram itself and uses four message types plus a 16-bit Message ID. The request/response layer handles application meaning with a Method or Response Code plus a Token. The message type is orthogonal to whether a datagram carries a request or a response: a single message is both a type (CON/NON/ACK/RST) and, usually, a request or response.

Confirmable (CON) asks for reliability: the sender expects an acknowledgment and will retransmit if none arrives. Non-confirmable (NON) is fire-and-forget: no acknowledgment, no retransmission. Acknowledgment (ACK) confirms one specific CON by echoing its Message ID. Reset (RST) says "I received your message but cannot process it" — for example when a node reboots and loses the context for an ongoing exchange.

A useful packet-trace habit is to name both layers for every datagram. Type=CON, Code=0.01 is a confirmable GET request; Type=ACK, Code=2.05 is a piggybacked Content response; Type=ACK, Code=0.00 is an empty acknowledgment that only stops retransmission; and Type=RST, Code=0.00 rejects an unexpected or unprocessable message. Looking at only the Code hides the reliability behavior.

Keep this straight: CON and NON are how you ask a resource question; ACK and RST are how the network layer reacts to a CON. A reading sent as NON is never retransmitted, so the next sample is your only recovery.

CoAP exchange patterns showing a confirmable request with acknowledgment, a non-confirmable message, a piggybacked response, and a separate response.
The estate figure focuses on the common exchange patterns built from CON, NON, and ACK; RST is the rejection path used when the receiver cannot process the message.

Confirmable (CON)

Elicits an ACK and is retransmitted on timeout. Use for commands, writes, and any message whose loss would leave wrong device state.

Non-confirmable (NON)

No ACK and no retransmission. Use for frequent, replaceable readings where the next sample corrects any loss.

Acknowledgment (ACK)

Confirms exactly one CON by echoing its Message ID. It may be empty, or it may piggyback the response.

Reset (RST)

Signals that a received message could not be processed for lack of context. It also answers a CoAP ping (an empty CON).

Practitioner: Reliability Is a Per-Message Decision With Named Timers

When you mark a message CON, you inherit RFC 7252's retransmission machinery, and its constants are worth knowing by name. The first retransmission timeout is a random value between ACK_TIMEOUT (default 2 s) and ACK_TIMEOUT × ACK_RANDOM_FACTOR (default 1.5, so up to 3 s). The timeout then doubles on each retry — binary exponential backoff — for up to MAX_RETRANSMIT (default 4) attempts. That yields a worst-case window of roughly 45 seconds (MAX_TRANSMIT_SPAN) before the sender gives up on that Message ID.

By default NSTART = 1, meaning an endpoint keeps only one CON exchange outstanding to a given destination at a time. This is deliberate congestion control for constrained links: a device cannot flood a sleepy peer with parallel confirmable traffic. If you need concurrency, you either raise NSTART carefully or use NON for the bulk traffic.

Worked Example: Valve Command vs Temperature Stream

A controller issues PUT /actuators/valve as CON because a lost "close valve" command is unsafe. The same node reports /sensors/temp every 10 seconds as NON because the next reading replaces the last. If the valve ACK is lost, the timeline below plays out; the temperature NON simply relies on the next sample.

Attempt
Timer (from RFC 7252)
Approx. wait before retry
Outcome if ACK still lost
Initial send
random(ACK_TIMEOUT, ACK_TIMEOUT × 1.5)
2 to 3 s
Retransmit #1
Retransmit 1
timeout doubles
4 to 6 s
Retransmit #2
Retransmit 2
timeout doubles
8 to 12 s
Retransmit #3
Retransmit 3 / 4
doubles until MAX_RETRANSMIT = 4
up to ~45 s total (MAX_TRANSMIT_SPAN)
Give up; report delivery failure to the app

Practitioner Checklist

  • Choose CON only where silent loss is unsafe; every CON can cost up to four retransmissions of radio-on time on a battery node.
  • Do not add an application-level retry on top of CON for the same message — you would duplicate the built-in exponential backoff.
  • Remember NSTART = 1: back-to-back confirmable writes to one peer serialize, so budget latency accordingly.
  • For a liveness probe, send an empty CON (a CoAP ping); a healthy peer answers with RST, which is cheaper than a full request.

Under the Hood: Piggybacked vs Separate Responses, and Duplicate Suppression

A server has two ways to answer a Confirmable request. In a piggybacked response, the ACK itself carries the answer: the same ACK that stops retransmission also holds the response code and payload (for example 2.05 Content). The ACK reuses the request's Message ID, and the Token matches the request's Token. This is the common case when the server can answer right away.

In a separate response, the server first returns an empty ACK (message code 0.00) to stop the client retransmitting, then sends the actual response later in a brand-new message — a fresh CON or NON with its own Message ID. The client recognizes it as the answer because the Token matches the original request. If that later message is CON, the client ACKs it in turn. Separate responses exist for resources that need time: waking a sensor, running a measurement, or querying a back-end.

sequenceDiagram
    participant C as Client
    participant S as Server
    Note over C,S: Piggybacked (answer ready now)
    C->>S: CON GET (MID, Token)
    S-->>C: ACK 2.05 Content (same MID, Token)
    Note over C,S: Separate (server needs time)
    C->>S: CON GET (MID, Token)
    S-->>C: ACK (empty)
    S->>C: CON 2.05 Content (new MID, same Token)
    C-->>S: ACK

CoAP message exchange showing header, token, options, and payload fields carried between client and server.
The Message ID ties an ACK to its CON at the messaging layer; the Token ties a response to its request at the request/response layer, which is what makes separate responses possible.

Because a CON can be retransmitted, a server may receive the same message twice. CoAP handles this with deduplication: the server tracks recently seen Message IDs per source endpoint for about EXCHANGE_LIFETIME (roughly 247 seconds with default timers). A duplicate CON must not be acted on twice; instead the server resends the cached ACK. This matters most for non-idempotent operations — a duplicated POST that appended a log entry, or a relative counter increment, would be wrong if processed twice.

Piggybacked

ACK carries the response. Same Message ID as the request, Token matches. Used when the answer is immediate.

Separate

Empty ACK stops retransmission, then a new CON/NON carries the response, correlated only by Token.

Message ID

16-bit field that pairs ACK/RST with a specific CON/NON and drives duplicate detection.

Dedup window

Servers remember Message IDs for about EXCHANGE_LIFETIME so a retransmitted CON is answered, not re-executed.

6.4 Release Checklist

Before signing off a CoAP message-flow design, verify that:

  • Each interaction names the Type, Code, Message ID, Token, and CON/NON policy.
  • ACK timeout, ACK random factor, maximum retransmits, and any NSTART change are recorded with their rationale.
  • Piggybacked and separate response cases are distinguished, including when an empty ACK is sent.
  • Duplicate cache lifetime, Message ID reuse policy, and non-idempotent operation handling are explicit.
  • RST behavior is defined for unknown tokens, lost Observe state, rebooted endpoints, and malformed messages.
  • The energy budget explains which traffic is allowed to be NON and what loss rate the application tolerates.

6.5 See Also

6.6 Next

After you can read a message exchange at both layers, continue with CoAP Message Format to inspect the exact bits and option fields carried in each datagram.