Transactions, Constraints, and Data Integrity

A transaction groups changes into a unit with defined atomicity and isolation behavior. Relational systems commonly provide multi-row transactions; document databases vary in transaction scope and cost. A transaction is useful when related state must change together, such as debiting one account and crediting another.

Constraints such as unique keys, foreign keys, and check constraints protect invariants at the data boundary. Application-level checks alone can race: two requests may both observe that a username is free and then attempt to insert it. A unique constraint is the final authority.

Keep transactions short and avoid slow network calls inside them. For workflows spanning independent services, a single database transaction may not be available; use patterns such as sagas, reservations, compensating actions, and reconciliation instead of pretending the whole workflow is atomic.

Define the invariant first

Write down what must never become false—for example, available inventory cannot be negative. Then choose constraints, transactions, and concurrency controls that enforce it.

Key Takeaways
  • Put critical invariants close to the data they protect.
  • Unique constraints prevent check-then-insert races.
  • Cross-service workflows need explicit recovery behavior.