flashman
← All guides

JSON Patch concurrency: indexes, identities, and safe updates

Design reliable JSON Patch APIs with stable identities, conditional requests, ordered operations, conflict handling, and regression fixtures.

2026-08-27 · 8 min read

  • json
  • api
  • concurrency

JSON Patch represents changes as an ordered list of add, remove, replace, move, copy, and test operations. It is compact and precise, but its JSON Pointer paths describe the structure of one document version. When that structure changes concurrently, a valid path may acquire a different meaning.

Arrays are the sharpest edge because numeric path segments identify positions rather than business entities. A client that read item C at /items/2 may later replace item D if another writer inserted an element at the front.

Understand operation order and pointer semantics

Apply operations in the listed order and evaluate each path against the result of previous operations. Removing /items/1 shifts every later index, so a second operation created against the original array may no longer target its intended value.

  • Escape tilde as ~0 and slash as ~1 inside pointer tokens.
  • Use the hyphen token only where appending to an array is defined.
  • Treat move as a remove followed by an add with ordering consequences.
  • Reject unknown paths instead of silently creating surprising structure.

Detect stale documents before mutation

Return an ETag or explicit version when clients read the resource, then require If-Match or an equivalent precondition with the patch. If the document changed, answer with a conflict or precondition failure and let the client refresh its intent.

A test operation can protect a specific value inside the document, but it is not a full replacement for transport-level concurrency control. Use both when the business invariant and the document version matter.

Prefer stable identity for collection members

If callers usually update one member by ID, a resource route such as /items/{id} is often safer than exposing its current array offset. When ordering is meaningful, give order its own field or operation and define how concurrent reorder requests conflict.

  • Assign durable IDs when items are created.
  • Avoid deriving identity from a mutable display name or position.
  • Return the updated representation and version after a successful patch.
  • Audit patches with IDs and versions, not sensitive full documents.

Test patches as state transitions

Keep fixtures for the base document, ordered operations, expected result, and expected failure cases. Include concurrent insertion, removal, reorder, a failed test operation, escaped pointer tokens, and a stale ETag.

Use Flashman's JSON formatter to inspect documents and operations, diff tool to compare state transitions, UUID generator for synthetic identities, and timestamp converter to reconstruct request ordering. These local tools help explain a patch, while server-side preconditions remain responsible for correctness.

Try these tools