Register
GET with Observe = 0. Server replies 2.05 Content plus an Observe option (starting sequence number).
A wall display receives a room temperature and then loses its connection. A green tile without a freshness warning can imply that the room is still being watched. An Observe client needs a freshness decision even when the value itself has not changed.
Treat Every Update as Fresh Only Until Proven Otherwise
Picture a clinic room sensor that sends a new temperature only when the value changes. A wall screen loses contact for ten minutes, then shows its last update beside a current time. The nurse may act on an old fact unless the client can tell its age and source.
CoAP is a web-style exchange method for small devices. Observe is its way for a client to ask for later updates. Record the client, server, request identity, update identity, start time, allowed age, last accepted order value, and rule for ending or renewing the request.
Delay one update, change their order, drop several, restart each side, let the age limit expire, and wrap the order value. Check that a late item cannot replace a newer one and that silence becomes an explicit unknown state rather than a false healthy state.
A successful message only proves delivery for that exchange. It does not prove sensor accuracy, a current room state, or continued server health. The screen must show age and uncertainty clearly enough for the nurse to choose a safe next step.
Practitioner builds the freshness and renewal policy. Under the Hood explains tokens, age fields, confirmation, order comparison, wrap rules, pacing, and the limits of best-effort updates.
Use this fresh-state review:
An alarm notification that arrives late can be worse than no notification if the client treats it as current. Observe therefore needs more than “server push”: the client must know which registration a notification belongs to, whether the value is fresh, and what to do when UDP reorders updates.
This page follows the subscription through token binding, Max-Age, liveness checks, sequence comparison, cancellation, and stale-update rejection so the pushed value can be trusted.
After this page, you should be able to:
Observe: 0 through token-bound notifications and cancellation.CoAP Observe Server Push teaches the main Observe pattern: replace repeated polling with change-driven notifications. This page narrows in on the deeper operational contract that makes the pattern safe: which token identifies the subscription, how long a value remains fresh, how the server detects unreachable observers, and how the client rejects stale notifications when UDP reorders datagrams.
The CoAP Observe contract therefore keeps the parent idea intact while adding the evidence needed for token binding, freshness, liveness, cancellation, and stale-update rejection.
Use it when an observed resource controls alarms, industrial telemetry, building automation, battery gateways, NAT-crossing clients, or any application where a stale pushed value could be mistaken for current state.
Observe (RFC 7641) adds a lightweight publish/subscribe relationship on top of plain CoAP request/response, using a single option numbered 6. A client registers by sending an ordinary GET with the Observe option set to 0. The server records the client — keyed by its source endpoint, its Token, and the requested resource — and answers 2.05 Content that itself carries an Observe option holding a sequence number. From that moment the client is an observer.
Whenever the resource's representation changes, the server sends a fresh 2.05 Content notification carrying an incremented Observe value and, crucially, the same Token as the original registration. That Token is how the client knows an unsolicited notification belongs to a subscription it opened. To stop, the client either sends a GET with Observe set to 1 (explicit cancel) or rejects a Confirmable notification with an RST.
A concrete trace shows the contract. If a dashboard registers GET /sensors/temp with Token 0x4a01, the server might answer 2.05 Content, Observe 12, and Max-Age: 60. Fourteen seconds later the pushed update uses a new Message ID but the same Token 0x4a01 and Observe 13. The client must keep that Token reserved while the observation is active; reusing it for another outstanding exchange would make later pushes ambiguous.
Inspect Figure to connect the registration exchange above with the server registry and notification state it creates.
Read Figure from message types and REST methods into the Observe relationship. The server keys an observer entry by endpoint, Token, and resource URI, then emits `2.05 Content` notifications with advancing Observe values when that resource changes. The Token preserves relationship identity while freshness rules order updates. Those separate responsibilities frame the failure and re-registration contracts developed next.
GET with Observe = 0. Server replies 2.05 Content plus an Observe option (starting sequence number).
On each change the server sends 2.05 Content with a higher Observe value, reusing the registration Token.
GET with Observe = 1, or reject a CON notification with RST, to end the relationship.
The Token ties every later notification to the subscription; without it the client cannot match a push.
Observe promises eventual consistency, not guaranteed delivery. Notifications are usually Non-confirmable, so any single one may be lost; the model only guarantees that the client eventually converges on the current state through later notifications. That has two practical consequences you must design for: freshness and liveness.
Freshness is governed by Max-Age. Each notification says how long its value can be considered current. A well-behaved server sends the next notification before the previous one's Max-Age expires, so a live resource never looks stale; if the client's Max-Age lapses with no new push, the client should re-GET (re-register) rather than trust an aged value. Liveness is checked with the occasional Confirmable notification: if its retransmissions all go unanswered, the server concludes the observer is gone and removes it, which is how "ghost observers" behind a closed NAT binding get cleaned up.
For example, a battery gateway observing /tank/level might send ordinary NON notifications only when the level changes by at least 2% or every 60 seconds, whichever comes first, with Max-Age: 120. The client treats silence for 120 seconds as stale and re-registers instead of assuming the last level is still safe. The server might make every tenth notification Confirmable, or use a five-minute CON probe, so closed NAT bindings and rebooted clients are detected without turning every update into an ACK exchange. If the sensor chatters around the 2% threshold, the server should coalesce changes and publish the newest value at the pacing limit; Observe reduces polling traffic only when push frequency is also controlled.
Because CoAP runs over UDP, notifications can arrive out of order: a client may receive an older reading after a newer one. If it simply trusted arrival order it would display stale data. The Observe option value — a number up to 24 bits wide that the server increments per notification — exists to solve exactly this, and RFC 7641 defines a precise comparison so wraparound does not fool the client.
Let V1 be the value of the notification the client currently accepts, received at time T1, and V2 the value of a newly arrived notification at time T2. The new notification is treated as fresher only if (V1 < V2 and V2 − V1 < 2^23) or (V1 > V2 and V1 − V2 > 2^23) — the two cases that correctly handle counter wraparound — or if more than 128 seconds have elapsed (T2 > T1 + 128 s), after which the later arrival simply wins regardless of value. Anything that fails all three tests is a reordered straggler and is discarded.
Suppose the client has accepted Observe 120 and then receives 124; because the difference is small and positive, 124 becomes the new displayed state. If 122 arrives two seconds later, it is discarded as a late datagram. Near wraparound, a server can move from 16777214 to 1; the large reverse numeric difference tells the client that 1 is actually newer, not older. After a long quiet period above 128 seconds, the client accepts the later arrival as a new baseline because old ordering evidence has expired.
This is why the Observe value must be read as a reordering sequence number, not as a reliable event counter. Lost Non-confirmable notifications mean the numbers a client sees can skip; the guarantee is ordering and eventual convergence, not that every increment is delivered.
Up to 24 bits, incremented per notification, used purely to decide which of two notifications is newer.
The 2^23 threshold distinguishes a genuine increment from a wrapped-around older value.
After 128 s, the later arrival is accepted regardless of the numeric comparison.
A notification failing all freshness tests is a reordered duplicate and is silently discarded.
Use an illustrative notification received at elapsed time 100 s with Max-Age of 30 s. Its freshness allowance runs out at 130 s if nothing renews it. At 125 s, 5 s remain. At 131 s, the display should follow its stale-data policy instead of presenting the temperature as current. Freshness measured from receipt does not establish the physical sample time unless the payload also carries it.
Suppose the accepted Observe value is 100, then 102 arrives, followed shortly by delayed value 101. Under the normal ordering comparison for this small interval, 102 is newer and 101 must not replace it. Skipping a sequence value does not by itself prove a lost critical event: notifications may represent changing resource state rather than a complete event history. An Observe application that requires every transition needs a separate durable event-history contract.
The freshness timer and ordering rule answer different questions. Ordering asks which representation is newer within the registration. Max-Age asks how long the accepted representation may be treated as fresh. A higher Observe value does not grant indefinite freshness, and an old packet arriving late must not silently renew confidence in an obsolete state.
Predict the result when the room stays at the same temperature but all later communication stops. The tile still becomes unknown when its freshness allowance expires; unchanged physical conditions cannot be inferred from silence. Next, restart the client and lose its reserved Token. A renewed Observe registration must not accept an arbitrary old notification as its own continuation.
This is why Observe contracts matter to alarm design. A display can keep the last temperature for context while marking its age and loss of freshness clearly. A separate warning can indicate that the monitoring path needs attention. Re-registration, confirmation and cancellation rules then restore a bounded relationship with the server. They do not turn best-effort updates into a guarantee that every physical event was observed.
Before shipping a CoAP Observe contract, verify these records:
Read these points as one connected sequence: start with Registration state is keyed by client endpoint, request Token, and resource URI, and the Token stays reserved while the observation is active; then Notification policy names which updates are Non-confirmable, which are occasional Confirmable liveness probes, and when failed probes remove the observer; then Freshness policy sets Max-Age for each observed resource and says what the client does when no notification arrives before that value expires; then Ordering policy implements the RFC 7641 24-bit Observe-value comparison, including the 2^23 wraparound window and the 128-second fallback; then Pacing policy documents change thresholds, coalescing, maximum notification rate, and evidence that Observe reduces traffic instead of creating a push flood; and finish with Recovery behavior covers explicit Observe: 1 cancellation, RST cancellation, client reboot with token loss, NAT binding expiry, resource deletion, and re-registration.
Read these points as one connected sequence: start with CoAP Observe Server Push for the parent tutorial and implementation workflow; then CoAP Message Types for CON, NON, ACK, RST, and retransmission mechanics; then CoAP Message Format for Token, option, and Message ID fields; then CoAP Implementation Labs for code patterns that maintain observer registries and notification pacing; and finish with MQTT Broker and Topics for a broker-mediated pub/sub comparison.
Return to CoAP Observe Server Push, then continue to CoAP Advanced Features for block-wise transfer and large-payload considerations.