Pattern 01
Read-modify-write without atomicity
What we see
A counter, a balance, a stock level, or a status transition implemented as: read the current value, compute the new one in application code, write it back. Under sequential requests this is correct. Under two concurrent requests, one of the two updates is silently lost — and no error is raised anywhere, because both writes succeeded.
Why an assistant produces it
Read-then-write is how the operation is described in English, and generated code follows the shape of the description. Expressing it as a single atomic statement requires knowing that concurrency is a concern, which the prompt did not say.
The pattern
const account = await db.account.findUnique({ where: { id } });
await db.account.update({
where: { id },
data: { credits: account.credits - cost },
});The fix
// Atomic in the database — the read and the write are one statement.
const updated = await db.account.updateMany({
where: { id, credits: { gte: cost } },
data: { credits: { decrement: cost } },
});
if (updated.count === 0) throw new InsufficientCredits();The correct implementation
Push the arithmetic into the database as a single statement, with the precondition in the WHERE clause so the guard and the write cannot be separated by another transaction. Where the logic is genuinely too complex for that, use an explicit optimistic-concurrency version column and fail the write when the version has moved — but a decrement is not too complex for that.
How to test it
Fire N concurrent requests at the endpoint and assert the final value equals the expected one. Ten parallel requests against a local database will surface it; you do not need a load testing tool. If the final value is non-deterministic across runs, you have found it.