Transactions and concurrency
Make each change all or nothing, and safe when two requests arrive at once. Send side effects such as email only after the data is safely stored.
- Required 3
- Recommended 3
Required
Wrap multi-step changes in a transaction
RequiredWhen one change writes several rows or tables, do it in one transaction, so it fully happens or not at all.
Make conditional writes
RequiredPut the condition into the write itself, so the database decides atomically. Never read a value, decide in the app and write it back.
Make writes safe to repeat
RequiredLet clients retry a write without doing it twice. Networks fail after the server has acted, so retries will happen.
Recommended
Know your isolation level
RecommendedKnow which isolation level each database uses by default, and raise it where a check and a write must see the same data.
Send side effects through an outbox
RecommendedWhen a change must also send an email, a webhook or a message, write that task to a table in the same transaction. Send it afterwards from that table.
Set aside messages that keep failing
RecommendedAfter a set number of failed attempts, move a message or job to a separate dead letter queue and alert. Never retry it forever or drop it.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers data playbook: https://agentwranglers.se/playbook/data/transactions-and-concurrency.