ToolPopToolPop
SQL · Lesson 7 of 8

Transactions & ACID, the UPI rule

11 min readUpdated 24 Jun 2026

You scan a QR code at a chai stall. 20 rupees leaves your account. 20 rupees lands in the stall owner's account. What happens if your phone dies after the debit but before the credit?

The answer is "nothing bad," and the reason is transactions. This is how databases keep banks, UPI, and your Swiggy order from falling apart when things go wrong.

Diagram
rendering diagram...
UPI transfer wrapped in a transaction. All or nothing.

A transaction is a group of statements that succeed or fail together

You wrap a bunch of SQL in BEGIN and COMMIT. Until COMMIT, nothing is permanent. If anything goes wrong, you ROLLBACK and it is as if none of it happened.

sql
BEGIN;
UPDATE accounts SET balance = balance - 20 WHERE id = 1;
UPDATE accounts SET balance = balance + 20 WHERE id = 2;
COMMIT;

Either both updates land, or neither does. There is no universe where 20 rupees disappears into the void. That guarantee is the whole point.

ROLLBACK: the undo button

If you spot a mistake mid-transaction, or your code throws an error, you call ROLLBACK instead of COMMIT.

sql
BEGIN;
UPDATE accounts SET balance = balance - 20 WHERE id = 1;
ROLLBACK;

The UPDATE is undone. Nothing was ever saved. This is why every backend framework wraps DB writes in a try/catch with a ROLLBACK in the catch block.

ACID: the four promises

Databases that support transactions promise four things. The acronym is ACID.

  • Atomicity. All statements in a transaction succeed, or none do. No half-finished states.
  • Consistency. The database moves from one valid state to another valid state. Constraints, foreign keys, and triggers are honoured.
  • Isolation. Two transactions running at the same time do not see each other's half-done work. Your UPI debit cannot read someone else's mid-flight credit.
  • Durability. Once COMMIT returns, the data survives crashes, power cuts, the works. It is on disk, written down, safe.

ACID is what separates a real database from a glorified spreadsheet. When the RBI mandates "no double debits, ever," ACID is the technical reason it actually holds.

The UPI example, end to end

sql
BEGIN;
 
UPDATE accounts SET balance = balance - 20
WHERE id = 1 AND balance >= 20;
 
UPDATE accounts SET balance = balance + 20
WHERE id = 2;
 
INSERT INTO transactions (from_id, to_id, amount)
VALUES (1, 2, 20);
 
COMMIT;

Three statements. One transaction. The balance >= 20 check inside the UPDATE is your "do you have the money" check, atomically built in. If account 1 has 19 rupees, the UPDATE matches zero rows, your app sees that, and you ROLLBACK instead.

When to use transactions

  • Any time you write to more than one row or table and they must agree.
  • Money movements, inventory changes, multi-step signups. Always.
  • Single-row updates are already atomic at the database level. You do not need an explicit transaction for a one-liner.

Try it on the right

Three transaction assignments. One of them asks you to ROLLBACK on purpose, which is more satisfying than it sounds. Next: window functions, the queries that make senior engineers nod approvingly.

Free tools you can use while you learn

Common questions

Q.What happens if my app crashes mid-transaction?
A.The database rolls back the uncommitted transaction on next startup. None of the partial changes survive. This is the Atomicity guarantee in ACID.
Q.Do all databases support transactions?
A.All serious relational databases do (Postgres, MySQL with InnoDB, SQLite). Some NoSQL stores support transactions only within a single document or shard. Always check before betting your data on it.
Chai0/2 done

Watching quietly. Tap me if you want a tip.

SQL Playground

Try this (0 of 2 done)

  1. 1

    After the transfer, show both account balances.

    hint

    SELECT * FROM accounts.

    show answer
    SELECT * FROM accounts ORDER BY id;
  2. 2

    Try a transaction that you ROLLBACK. Balances should NOT change.

    hint

    BEGIN; UPDATE ...; ROLLBACK;

    show answer
    BEGIN;
    UPDATE accounts SET balance = 0 WHERE id = 1;
    ROLLBACK;
    SELECT * FROM accounts;