Developer Offshore guide

Use HTTP ETags to Stop Lost Updates in Distributed Product Work

A reviewable way to connect validators, conditional requests, conflict responses, and user recovery without treating an ETag as magic locking.

Source-backed guidanceContextual internal linksTop, middle, and bottom CTAs
Use HTTP ETags to Stop Lost Updates in Distributed Product Work

Use HTTP ETags to Stop Lost Updates in Distributed Product Work

  • Define the representation covered by the validator.
  • Require a matching precondition for unsafe replacement.
  • Give users a deliberate conflict-recovery path.

Start with the lost-update story

Picture two editors opening the same customer-visible description at version 14. Ana changes the support instructions and saves version 15. Ben, whose screen still shows version 14, changes only the title and submits the entire older document. Without a precondition, Ben’s replacement can restore the obsolete support text while appearing to save successfully. The defect is not simultaneous typing by itself. It is an unsafe write accepted without proving which prior state the writer intended to replace.

Write that sequence as a fixture before choosing headers. Identify the resource, representation, read response, local edits, intervening change, write method, expected conflict, and recovery experience. Decide whether the operation replaces the whole representation, patches named fields, appends an event, or invokes a command. Conditional requests are especially useful for replacement and state-dependent changes, but the application still owns merge meaning. An ETag cannot decide whether two edits are semantically compatible.

Define what the validator identifies

A strong entity tag is an opaque validator for a selected representation. Document whether it changes when persisted fields change, when computed fields change, when permissions hide fields, or when content negotiation produces another form. Do not expose a database timestamp or revision number casually if that leaks information or fails to change for distinct states. The value can be generated from an internal version or content digest, but clients must treat it as opaque.

Compression and other transformations complicate representation identity. A validator attached to JSON is not automatically valid for an HTML view or a user-specific projection. Exercise authorized users who see different fields, language variants, and any gateway that rewrites the response. If the same URL emits materially different bytes or semantics, verify that cache metadata and validators distinguish them correctly. A shared ETag must never become evidence that two users were entitled to the same private representation.

Require the precondition on the write path

Return the current ETag with the read response and have the client send If-Match when it updates that version. The server evaluates the precondition atomically with the mutation. Checking the value in application code and writing later can recreate the race between those operations. The persistence layer needs a compare-and-change boundary, such as an update constrained by the expected version, whose affected-row result is interpreted deliberately.

Decide what happens when If-Match is absent. For a route that promises lost-update protection, accepting an unconditional replacement because an older client omitted the header defeats the contract. A precondition-required response can be appropriate, while a mismatched supplied validator should produce the protocol’s precondition failure. Keep validation, authorization, not-found handling, and precondition evaluation ordered so responses do not disclose a resource the caller cannot access.

Test concurrency rather than a serial imitation

Create one record and obtain the same validator in two independent clients. Pause both before the write, release them together, and assert that only one state-dependent mutation succeeds. The rejected request must not emit side effects, enqueue duplicate work, or update an audit record as though it succeeded. Repeat across application replicas and against the actual database isolation and proxy path used by the service. A unit test around string equality does not prove atomic mutation.

Add cases for a stale tag, malformed syntax, a tag from another resource, a weak validator where strong comparison is required, a wildcard if supported, deletion between read and write, and a retry after the client fetches the new state. Observe status, response body, database version, emitted events, and audit result. Use synthetic records so the evidence can travel across working hours without exposing customer data.

Design recovery for a person, not only an API client

A conflict response should let the interface explain that the record changed after it was opened. Preserve the user’s proposed values locally, fetch the current server representation, and show the fields that differ. Simple non-overlapping edits may be mergeable under an explicit product rule; overlapping or consequential changes should remain a user or owner decision. A blind retry with the new ETag merely converts a detected conflict into an overwrite.

Accessibility belongs in this state. Move focus to a clear conflict heading, announce the changed status, label original, current, and proposed values, and keep keyboard access to review controls. If sensitive fields cannot be redisplayed, explain the safe next action without echoing hidden data. Product owners define merge rules and wording. The developer builds the mechanics and demonstrates that rejected writes preserve both server truth and the person’s unsaved work.

Separate cache validation from write safety

If-None-Match on a safe read can avoid transferring an unchanged representation. If-Match on an unsafe request can guard the intended prior state. They use validators but answer different questions. Test gateways and SDKs so a caching layer does not strip a request precondition or synthesize an unrelated validator. Also verify that a 304 read path preserves the client’s association between its cached body and validator.

Monitor precondition failures by route and client version, but do not label every conflict an error. Some failures prove the control worked. Investigate sudden changes: an increase may reveal a new editing pattern or stale client, while zero conflicts can mean the header disappeared. Retain enough correlation to reproduce the sequence without logging private bodies. Metrics should distinguish missing preconditions, mismatches, successful guarded writes, and recovery outcomes.

Hand off an enforceable contract

The delivery record should name the protected routes, representation definition, validator generation rule, required headers, atomic persistence check, response semantics, UI recovery, concurrency fixtures, authorization cases, metrics, known unprotected clients, rollout sequence, and rollback. Include exact revisions and passed or skipped environments. The API owner approves compatibility and merge semantics; the data or product owner decides consequential conflict resolution; the offshore developer can implement, test, and document the bounded change.

Review the first real conflict after release rather than assuming the fixture represented every workflow. Reopen the work if users cannot understand the recovery, intermediaries alter headers, or a side effect occurs on a rejected mutation. Teams considering offshore API support can use this packet as a first assignment: it has an observable failure, bounded code paths, clear owner decisions, and evidence another time zone can review.

Use the assessment in your hiring plan

Node.js API developmentQA automation engineeringContact Developer Offshore

Questions about assessing Philippine developers

Does an ETag replace database locking?

No. The server still needs an atomic compare-and-change operation. The validator carries the client precondition; persistence must enforce it without a race.

Should a client automatically retry after a precondition failure?

Not by overwriting with a new validator. Fetch current state and apply an explicit merge or user decision before trying again.

Sources

  1. IETF RFC 9110: HTTP Semantics: Entity tags and conditional request semantics.
  2. MDN: ETag: Practical validator and lost-update examples.

International Labour Organization guidance on remote work arrangements reinforces why remote role briefs should document expectations, communication rhythms, and accountable handoffs.