Two staff members open the same inventory record. It shows 12 units. One receives a delivery and updates the count to 17. The other finishes a count based on the old screen and saves 11. Both requests succeed, but the second save silently wipes out the first.
If you control the REST API, you can make the second save stop and ask for a fresh look. Return a version of the record as an ETag, then require clients to send it back in If-Match when they edit. The database must enforce that check at the moment it writes.
Send the version the editor actually saw
On GET /inventory/42, return the count and a strong ETag such as "stock-42-v7". The editor should keep that tag alongside the displayed data. When the first employee saves 17, send PATCH with If-Match: "stock-42-v7". If the record is still on version 7, save the new count, advance the version to 8, and return the updated representation and tag.
The second employee’s request still carries version 7. The server compares it with the current version and returns 412 Precondition Failed without applying the stale update. RFC 9110’s If-Match section describes strong comparison and conditional requests. Keep the tag quoted and avoid a weak W/ prefix for this use. The example assumes one JSON representation; if the API serves different representations, make sure its validators distinguish them where required.

An open carton of small product boxes beside two sealed cartons on a worn metal shelf. Fictional AI-generated editorial image.
Fictional editorial image: cartons on a stockroom shelf.
Check and write in the same database operation
A controller that reads the current version, compares it in PHP, and then saves without a condition still has a race. Another request can update the row between the comparison and the write. Put the record ID and expected version in the update’s WHERE clause and increment the version as part of that same update.
In Laravel, use the query builder to scope the row to the authorized account and expected version, then update the validated fields and increment the version. The Laravel query builder documentation explains that update returns the number of affected rows. In this design, one affected row means the change won. Zero means the write did not apply; distinguish a stale version from a missing or inaccessible record using your API’s normal resource and authorization rules.
Every write path that changes the protected representation needs to advance its version. If an import or admin screen updates stock without doing so, the API can accept an edit based on an old count. Check these paths before relying on the tag.
Give people a way to resolve the conflict
If the endpoint requires a precondition and the client omitted it, RFC 6585’s 428 Precondition Required gives you a response for that case. Use a clear error message explaining that the client must load the record and submit its version. A supplied tag that no longer matches is a different case: return 412 and preserve the user’s draft on the client.
For the inventory example, show “You started with 12, the current count is 17, and your draft says 11.” Ask the employee to confirm whether 11 was a fresh physical count or an adjustment of minus one. If the action really means “subtract one,” a purpose-built adjustment endpoint can apply that change to the current value, subject to business rules and protection against duplicate submissions. Don’t automatically fetch a fresh tag and replay an absolute overwrite.
Test the conflict before enabling the rule
- Open the same record in two sessions. Save from one and confirm that the second receives 412 without overwriting it.
- Send a write without If-Match and verify that the response explains how to retry with a valid precondition.
- Make a change through the import or admin path, then submit the older API tag. Confirm the stale edit is rejected.
- Run simultaneous saves with the same tag. Exactly one should win when both are valid and target the same version.
- Check that the rejected editor retains its unsaved input and can reload the latest record for review.
For related internal operations work, see my Maven Pro intranet project. If staff are overwriting each other’s edits in an admin tool, I can help trace the write paths and decide where a version check or an adjustment endpoint makes sense.



