On this page
  1. What does ACID mean?
  2. What happens without a transaction?
  3. How do I use transactions in code?
  4. Where AI coding assistants get this wrong
  5. Checklist
  6. FAQ
    1. Is every single INSERT wrapped in a transaction?
    2. What is the difference between a transaction and a lock?
  7. Related topics
  8. Sources
concept

What Is a Database Transaction (ACID)?

A transaction groups database operations so they all succeed or all roll back. Learn ACID, why transfers need it, and how to use it in code.

Quick answer

  • A transaction is a group of database operations that commits together or rolls back together — no partial states.
  • It’s what keeps a bank transfer from debiting one account without crediting the other.
  • Wrap multi-step writes in a transaction, and use the ORM or driver’s begin/commit/rollback API.

What does ACID mean?

ACID is the property set that makes transactions reliable. Atomicity: all operations commit or none do. Consistency: the database moves between valid states. Isolation: concurrent transactions don’t see each other’s partial work. Durability: a committed transaction survives crashes. Each letter maps to a failure mode — without atomicity a crash mid-transfer leaves half the money moved; without durability a power loss forgets the commit. Databases implement these with logs, locks, and snapshotting under the hood.

What happens without a transaction?

Each SQL statement commits on its own. A transfer is two statements — debit, credit — and if the process crashes between them, or the second fails, you have a permanent inconsistency: money gone from one account, never added to the other. Any multi-step write has this shape: order + payment + inventory updates, a profile update across two tables. Without a transaction, each step is a separate commit point and failure leaves the data in whatever state the crash happened to produce.

How do I use transactions in code?

Wrap the operations in begin/commit, and roll back on error. ORMs and drivers provide this; in SQLAlchemy it’s with db.session.begin(): and in raw SQL it’s explicit BEGIN/COMMIT/ROLLBACK. Two practical notes: keep transactions short (long ones hold locks and block other writers), and don’t put slow external calls — HTTP requests, LLM calls — inside a transaction, because the locks stay held while you wait.

# SQLAlchemy: everything in the block commits together, or rolls back\nfrom sqlalchemy import text\n\nwith engine.begin() as conn:  # commits on success, rolls back on error\n    conn.execute(text("UPDATE accounts SET balance = balance - 100 WHERE id = 1"))\n    conn.execute(text("UPDATE accounts SET balance = balance + 100 WHERE id = 2"))

Where this bites vibecoders

AI-generated code that touches money or inventory without transactions is a silent data-corruption generator: it works in the demo, and the corruption only appears when a request dies mid-write under real traffic. The assistant usually generates each write as a standalone statement because that’s the simplest shape. Asking ‘should these writes be one transaction?’ — and wrapping them — is a two-line change that converts a latent corruption bug into a correct operation.

Where AI coding assistants get this wrong

  • Multi-step writes with each statement auto-committing, so crashes leave partial states.
  • Putting slow external calls inside transactions, holding locks while waiting on the network.
  • Catching errors and swallowing them without a rollback, leaving the transaction open.
  • Assuming the ORM auto-wraps every multi-statement block in a transaction — it doesn’t.

Checklist

  • Wrap every multi-step write in an explicit transaction.
  • Keep transactions short — no external calls or long computations inside.
  • Roll back on error; never swallow an exception and leave the transaction open.
  • Test the crash path: kill the process mid-transfer and confirm the data stays consistent.

FAQ

Is every single INSERT wrapped in a transaction?

Yes, implicitly — a single statement is its own transaction that commits on completion. The problem is multi-statement operations, where each statement commits separately unless you group them. That’s the case where explicit transactions matter.

What is the difference between a transaction and a lock?

A transaction is a grouping of operations that commit or roll back together. A lock prevents other transactions from touching data concurrently. Transactions use locks for isolation, but you can also lock without a transaction — the concepts are related, not the same.

Sources

Share: