Read-back check

Last checked · 3 min read

A read-back check reads a record again right after a write and compares it, field by field, with what the agent or app meant to save. It catches a write the server answered with success but stored differently, or not at all. It checks the record it reads, not the side effects elsewhere.

Why a success reply isn’t enough

A write API answers with a status code. A 200 or a 201 says the server accepted the request. It doesn’t say the stored record holds what the client sent. In FHIR, for example, a create sent with If-None-Exist that matches one existing resource is ignored: the server answers 200 OK and creates nothing.1 An update sent with an old version in If-Match gets 412 Precondition Failed, and nothing is written.1

Other gaps come from the server’s own rules. Access rules can make a field read-only, so the server saves the record without it. A server can replace an id the client chose, or set the author to the app that sent the request. On Medplum 5.2.6 without its transaction-bundles feature, an all-or-nothing batch with one invalid entry was answered 200, and two of its three readings were stored.4

When we measured this, a check that trusts the status code caught none of the 11 cases where the server said success and stored something else.3

How a read-back works

  1. Write the record and keep the server’s answer, including the id and version it reports.
  2. Read that record again, at that version if the API allows it.
  3. Drop the fields the server sets on its own, such as timestamps and version numbers.
  4. Compare each field the client sent with the stored value, and flag any difference.

The comparison is the useful part. “The record exists” is a weaker check than “the record holds what we meant to save”.

What a read-back can’t see

A read-back reads one record. It misses what happens around it:

  • Extra records. A retry that saves the same reading twice leaves two records. Reading back one of them looks fine.
  • Partial batches. If one entry of a batch was dropped, a read-back of the entries that were stored passes.
  • Records the server made instead. A conditional update with no match can create a new record rather than change the old one.
  • Later changes. Another system can change the record a second after the read-back.

For those, you need the server’s own change log, or a rule that stops the risky call before it runs. On the 6 controls of our benchmark, where the agent was right, Deedglass raised 0 false alarms.3

Read-back, log check, or both

A read-back works with any API you can read from, which is why it suits FHIR servers and REST tools. A check against the database’s change log sees every row a transaction committed, including triggers and cascades, but needs access to that log. Where both are possible, the log check sees more. Where only the API is open to you, a read-back is far better than trusting the status code.

An example

Scenario 01 of the FHIR benchmark, from the results table (corpus/fhir/results/latest.md, run of 21 October 2026)text
| Scenario | Server | The agent reports | Stored without a gateway | none | http-status | deedglass |
|---|---|---|---|---|---|---|
| `01-conditional-create-match` | medplum | create 1 Observation | nothing | **missed** · effect no · record no | **missed** · effect no · record no | caught after the write · effect yes · record yes |

How Deedglass uses it

Deedglass's FHIR connector reads each write back at the version the server reported and compares the fields the agent sent one by one, after dropping what the server adds on its own, such as version details and a generated narrative.2 In our FHIR write benchmark on Medplum 5.2.6, Deedglass caught 4 of the 11 cases where the server said success and stored something else: 3 by reading the write back and 1 by a rule that refused a delete.3 It missed 7, including a duplicate from a retry and a batch applied in part.3

Related on this site

Sources

  1. 1HL7 FHIR R4: RESTful API · hl7.org · checked 25 October 2026
  2. 2Deedglass docs: the FHIR connector · docs.deedglass.com · checked 25 October 2026
  3. 3Deedglass source: corpus/fhir/results/latest.json, the FHIR benchmark run of 21 October 2026 · github.com · checked 25 October 2026
  4. 4Deedglass source: corpus/fhir/BENCHMARK.md, the method and the limits · github.com · checked 25 October 2026

Last checked 25 October 2026. We re-check the glossary every month. If something here is wrong, write to hello@deedglass.com.