Two people open the same customer order. One changes the delivery address while the other updates a reference number. Both press Save, and the second submission quietly restores the old address because its form contained an earlier copy of the record. Each person saw a successful response, but one accepted change disappeared.
This is a lost-update problem. It can affect ordinary administration screens as well as imports, mobile synchronisation and background processes. Optimistic concurrency is one approach to detecting that the underlying information changed after it was read, allowing the application to resolve the conflict deliberately rather than overwriting it by accident.
Identify where competing changes matter
Start with records that several users or processes can edit. Include long-lived forms and workflows that save information after a delay. A screen used by only a few people can still have significant conflict risk when one person leaves it open for an hour while another works on the same record.
For a hypothetical logistics company, delivery instructions, assignment status and billing references may be updated by different roles. List which changes are independent and which can invalidate another person's decision. This gives the team a business basis for choosing conflict behaviour.
Review non-interactive writers as well. A nightly integration that updates a customer record can compete with an administrator's browser session. Protecting only the screen's save button leaves the underlying problem unresolved if another application path can overwrite the same information without a compatible check.
Detect that the record changed
EF Core supports optimistic concurrency through configured concurrency tokens. During an update or delete, the original token participates in the operation; if the expected row is not affected, EF Core can report a concurrency conflict. SQL Server's rowversion is one database-specific option, and it is not a date or clock timestamp. EF Core concurrency documentation.
Carry the original version from the read operation through the client's attempted update. If the server simply reloads the current version and treats it as the client's original, it can lose the evidence needed to detect a stale form. Keep the version's role clear in request contracts and tests.
Treat the submitted version as a concurrency condition, not permission to edit. The application must still authenticate the caller, verify record ownership and validate the requested operation. A correct conflict check does not replace the ordinary access and business rules around the update.
Decide what a conflict means for the user
Choose a response that fits the data. For a low-impact independent field, a controlled merge may be possible. For a delivery address or approval state, the user may need to review the current record and decide again. Avoid applying one silent overwrite policy to every business operation.
Preserve the user's attempted changes long enough to compare them with current information. A conflict message that clears the form and asks the person to start again can turn a protective mechanism into a frustrating loss of work. Present the relevant differences in language the user understands.
For the logistics example, show that the address changed while the form was open and identify the conflicting fields where appropriate. Let the user retain a reference-number change only if doing so is consistent with the workflow. Record an explicit override when the business requires accountability for that choice.
Keep conflict resolution connected to business rules
Revalidate an operation against the current state before accepting it. An order that was editable when loaded may now be dispatched. Even if a field can technically be merged, the business may no longer permit changing it through the same path.
Consider operations that span several records. A token on one row does not automatically protect every related invariant, such as a capacity limit calculated across several reservations. Use an appropriate transaction and database strategy for the rule, and test the competing operations that could violate it.
Distinguish an update conflict from an initial duplicate creation. A concurrency token on an existing row does not solve every race to create a new record. Uniqueness constraints and a meaningful request identity may be required for those cases. Keep the chosen mechanism matched to the failure it is intended to prevent.
Handle retries according to the operation
Some automated operations can reload the current state, recompute their intended change and retry a limited number of times. Others require a new business decision. Repeating a stale update unchanged can produce repeated conflicts or eventually apply an outcome that no longer matches the original intent.
Bound automated retries and make persistent contention visible. If a background job continuously competes with an interactive workflow, the underlying ownership or operation design may need attention. Treat that pattern as evidence to investigate rather than simply increasing a retry count.
For user-driven changes, explain whether the operation was rejected, partially applied or left pending. Prefer transaction designs that make the relevant outcome clear. A generic “Something went wrong” response encourages repeated clicks and makes it harder for support to determine which change actually reached the database.
Test competing behaviour and monitor the result
Create tests that read the same record twice, apply one change and then attempt the stale update. Check both the database outcome and the response shown to the caller. Include deletion, revoked permissions and important state transitions, not just two edits to an unimportant text field.
Exercise the real persistence mechanism for behaviour that depends on the database. A substitute provider or an in-memory object can have different concurrency semantics. Keep focused tests for the selected database alongside faster rule checks, and document what each layer proves.
Worktechlabs can help improve reliability in multi-user business applications, including offline workflows and domain rules. Make competing changes an explicit product behaviour, preserve users' work during resolution and measure recurring conflicts so the team can improve the workflow as well as the save operation.
Official sources and further reading
- Microsoft: handling concurrency conflicts in EF Core — tokens, conflict detection and resolution approaches.
- Microsoft: domain-model validation — preserving business invariants when applying changes.

