Optimistic Concurrency Guard

Optimistic concurrency detects that the facts behind a decision have changed. A conflict should trigger a new decision, not a blind retry.

Database · SQL

Optimistic Concurrency Guard

A decision is valid only against the version of state it observed.

UPDATE subscriptions
SET plan = $1, version = version + 1, updated_at = now()
WHERE id = $2 AND version = $3
RETURNING *;
-- Zero rows means conflict: reload state; do not silently retry the decision.

Invariant: A write succeeds only against the exact version the decision observed.

Use when: Two writers may update the same aggregate and lost updates are unacceptable.

Why this boundary matters

A version predicate turns a silent lost update into an explicit conflict. The business decision must then be recomputed against current state.

Failure policy

BoundaryAction
Version matchesCommit the update and increment the version
Version mismatchReturn a conflict and reload current state
Automatic retry requestedRe-run the business decision, not only the SQL
Aggregate is consistently hotReconsider partitioning, serialization, or pessimistic locking
External side effect follows updateUse an outbox or equivalent atomic handoff

Trade-offs

Optimistic concurrency avoids blocking when conflicts are rare, but repeated conflicts waste work and hurt latency on hot aggregates. It detects stale decisions; it does not merge them.

Decision rule: Use optimistic control when conflicts are exceptional and the caller can explicitly resolve or recompute a stale decision.

Further reference

Browse all engineering snippets

>