Concurrency control
Count conflicts separately from failures
A rejected competing write may show that protection worked. Measure its user impact and recovery outcome without treating every conflict as an infrastructure incident.
In this article
Classify the outcome at the right level
A stale document edit, exhausted booking capacity and a database connection failure need different responses. Combining them into one error rate hides both product friction and operational faults.
Record the business operation, conflict category and final outcome using bounded labels. Keep individual record identities in controlled diagnostic events rather than metric dimensions.
Distinguish a conflict returned to the user from a transaction retry that eventually succeeds. Both consume time, but only one necessarily interrupts the user's task.
Measure the full attempt
Track time from the initial request to a confirmed result, including retries and waiting. A fast final database attempt can hide several seconds spent contending earlier.
Count attempts per completed operation and the proportion that exhaust the retry budget. Rising retries can indicate a newly hot record or an unnecessarily broad transaction boundary.
Also inspect abandoned tasks after an edit conflict. A technically correct rejection can still be a poor experience if the interface discards the draft or makes comparison impossible.
Monitor the invariant directly
Where feasible, run reconciliation checks for the rule being protected. Examples include capacity never falling below zero and each operation identity producing at most one committed effect.
Choose checks that match the model. A temporary reservation and a confirmed booking may both consume capacity, so a naive count of confirmed records can miss the actual allocation.
Investigate any invariant violation independently of the conflict rate. Zero reported conflicts is not success if an unprotected writer silently overwrites data.
Set useful release criteria
A concurrency change should preserve the business rule under controlled races, keep latency within the agreed budget and provide an understandable outcome to the losing request.
Use workload-specific thresholds for acceptable contention. A shared daily counter behaves differently from independent customer records. Do not import a universal conflict percentage from another application.
Compare before and after using the same workload distribution, including hot keys. An average spread across thousands of quiet records can make a heavily contested resource disappear from the report. The measures should explain both correctness and the experience of the people who encounter contention.
Primary sources
PostgreSQL: transaction isolationReferences checked 11 September 2026.