skip to content

Which RESTCONF resources carry an ETag and Last-Modified, what updates them, and what can a client safely conclude from them?

level: seniorimportance: should knowfreq 8%

answer

  1. no locks, so detect instead
  2. datastore MUST, data resource SHOULD
  3. configuration only, never state
  4. a change ripples upward
  5. one tag per representation

basics

~20 s

The datastore resource must carry an ETag and should carry Last-Modified; configuration data resources should carry an ETag and may carry Last-Modified, otherwise reusing the datastore's. Only configuration changes update them — on the node, its ancestors and the datastore.

solid answer

~50 s

RESTCONF has no locks, so RFC 8040 gives clients edit-collision *detection* instead. The datastore resource `{+restconf}/data` MUST have an opaque entity-tag returned as `ETag` on retrieval, and SHOULD keep a timestamp returned as `Last-Modified`. A configuration data resource SHOULD keep its own entity-tag and MAY keep its own timestamp; when it does not, the datastore's value MUST be used instead. A configuration change updates the tag and timestamp of the changed node, every ancestor, and the datastore; changes to non-configuration (state) data MUST NOT touch them. Each representation, XML or JSON, needs its own entity-tag. So a matching tag means *the configuration this tag covers is unchanged*: it says nothing about counters, and access-control changes do not alter it either. Clients send the tag back in `If-Match` on an edit to avoid overwriting a change they never saw.

go deeper

for a junior

Recall that RESTCONF returns an ETag and Last-Modified so a client can notice that configuration changed between its read and its write.

for a middle

Explain which resources must or should carry the tags, the datastore fallback, and that only configuration changes, rippling upward, update them.

for a senior

Show what a matching tag does and does not prove — state data, per-representation tags, NACM changes — and build a read-modify-write loop that handles refusals.

for a principal

Weigh coarse datastore-level tags against per-resource tags for a high-churn automation estate, and decide where optimistic concurrency is enough without locks.

## Why RESTCONF needs edit-collision detection **RESTCONF** (RFC 8040) is stateless: there is no session, no `<lock>` and no commit for the client to hold. Two automation jobs, or a job and an engineer on the device's own interfaces, can therefore read the same configuration, change it and write it back, the second silently undoing the first. RFC 8040 §3.4.1 answers with **edit-collision detection** built on two pieces of HTTP metadata: - an **entity-tag** — an opaque string the server changes whenever the resource changes, returned in the `ETag` header; - a **timestamp** of the last change, returned in the `Last-Modified` header. A client keeps the value it read and sends it back on its edit; the server refuses the edit if the resource has moved on since. The HTTP precondition machinery that does the refusing (`If-Match`, `If-Unmodified-Since`, the `412` answer) is HTTP's own, now defined in RFC 9110, which obsoletes the RFC 7232 that RFC 8040 cites. What RESTCONF adds is *which resources carry the metadata and what changes it*. ## Who carries what | Resource | Entity-tag (`ETag`) | Timestamp (`Last-Modified`) | If the server keeps none | |---|---|---|---| | Datastore `{+restconf}/data` | **MUST** be maintained and returned on retrieval | **SHOULD** be maintained | — | | Configuration data resource | **SHOULD** be maintained, returned on `GET`/`HEAD` | **MAY** be maintained | the datastore's value **MUST** be used | | Non-configuration (state) data | not defined by RFC 8040 | not defined | — | | Operation resource | not applicable — operations are invoked, not read | — | — | The fallback row is the practical surprise. On a server that keeps only the datastore's tag, every data resource reports the *same* tag, so any configuration change anywhere on the device makes every cached tag stale. ## What updates a tag 1. **A configuration change to the node or anything below it.** RFC 8040 §3.5.2: the tag must change whenever the resource or any configuration resource within it is altered. 2. **Every ancestor.** §3.4.1.3's example: setting `/interfaces/interface/enabled` changes the `enabled` leaf, that one `interface` entry and the `interfaces` container. 3. **The datastore**, whenever any top-level configuration node changes — which any configuration edit does, through its ancestors. 4. **Other protocols.** When RESTCONF is co-located with NETCONF, the tags and timestamps must describe the `running` datastore, so a NETCONF edit to `running` moves them too; RFC 8040 notes other mechanisms may as well. And what must **not** update them: changes to non-configuration data. Counters, operational status and learned state never change a RESTCONF entity-tag or timestamp. ## What a client can and cannot conclude - **Same tag means same configuration, not same response.** Because state data is excluded, a resource whose `GET` includes counters can return different bodies under one tag. - **Tags are per representation.** RFC 8040 §3.4.1.2: XML and JSON representations need different entity-tags. A tag read as JSON should not be compared with one read as XML. - **Access-control changes are invisible.** §4.3: the `ETag` and `Last-Modified` of a data resource are not affected by changes to NACM rules, so what one client is allowed to see can change with no change in the tag. - **A fallback tag over-reports.** If the tag is the datastore's, a collision may be reported for an edit somewhere else on the device. Safe, but noisy for busy devices. - **Timestamps are coarse.** `Last-Modified` has one-second resolution in HTTP, so two edits in the same second can share one; the entity-tag is the stronger guard. ## Using them in an automation loop 1. `GET` (or `HEAD`) the resource the job is about to edit and keep its `ETag`. 2. Compute the change. 3. Send the edit — `PUT`, `PATCH` or `DELETE` — with that tag in `If-Match`. 4. On a refusal, `GET` again, recompute against what is now there, and retry or escalate; never resend blindly. RFC 8040 §5.5 adds a reading-side rule: since datastore content changes at unpredictable times, responses generally SHOULD NOT be cached, every response MUST carry `Cache-Control`, and clients SHOULD track `ETag`/`Last-Modified` themselves, using `If-None-Match` or `If-Modified-Since` on a retrieval to get `304 Not Modified` when nothing has changed.

  • A RESTCONF server returns the same ETag for every data resource. Is it broken?
    Not necessarily. RFC 8040 makes per-resource entity-tags a SHOULD, and a server that does not keep one MUST use the datastore's tag instead. The result is correct but coarse: any configuration change anywhere on the device invalidates every tag a client holds, so guarded edits on a busy device are refused more often and need a re-read and retry.
  • An operator tightens NACM so that one automation account can no longer read a subtree. Does that account's cached ETag reveal the change?
    No. RFC 8040 says the `ETag` and `Last-Modified` of a data resource are not affected by changes to access-control rules. The account's view of the resource shrinks while the tag stays the same, so a client cannot use the tag to detect that its visible representation changed for authorisation reasons.

saying these in an interview costs you the question

  • Every RESTCONF data resource is required to carry its own ETag.
  • An interface counter incrementing changes the resource's ETag.
  • A JSON GET and an XML GET of one resource return the same ETag.
  • If a data resource keeps no ETag, the server sends no ETag header.
  • An unchanged ETag proves the GET response body is unchanged.