1Dirty Reads
While your transaction is running but not yet committed, can other users read the temporary data? This depends on the 'Isolation Level'. By default in Postgres (Read Committed), other users will only see the old data until you hit COMMIT. This prevents 'Dirty Reads'.
2Step-by-Step Breakdown
The Problem. Imagine a Bank Transfer. You UPDATE Alice's balance (-$100). Then the power goes out. The server crashes BEFORE it can UPDATE Bob's balance (+$100). The $100 is lost forever. This is catastrophic.
Transactions (BEGIN). To prevent this, we use Transactions. You type 'BEGIN;'. This tells the database: 'I am about to do several things. Do not save ANY of them to the hard drive yet.'
Executing the Block. Inside the transaction, you run the DML. 'UPDATE alice SET bal = bal - 100;'. 'UPDATE bob SET bal = bal + 100;'. The database performs these in a temporary memory space.
COMMIT. If both commands succeed without error, you type 'COMMIT;'. This tells the database to permanently write the temporary changes to the hard drive simultaneously.
Knowledge Check. If a Node.js backend throws an error halfway through a multi-step database transaction, what command must Node issue to the database to cancel the partial changes?
- →CANCEL;
- →ROLLBACK;
ROLLBACK. If an error occurs ANYWHERE in the block (e.g. Bob's account doesn't exist), you catch the error and type 'ROLLBACK;'. The database instantly throws away the temporary changes. Alice keeps her $100.
ACID Properties. Transactions are how databases guarantee 'Atomicity' (the 'A' in ACID). The block is Atomic: it either 100% succeeds, or 100% fails. No half-measures.
DROP Database. Moving to DDL: The ultimate destructive command. 'DROP DATABASE my_app;'. This destroys the entire database, all tables, and all data instantly. Cannot be rolled back in most engines.
Node.js Integration. In a Node API, you will use your DB driver (like pg) to run client.query('BEGIN'), do your logic, and run client.query('COMMIT') or client.query('ROLLBACK') in the catch block.
Summary. You have completed the SQL Track. You are ready to build robust backends.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Long-Running Transactions Need a Visible Pending State
If an admin tool lets a user BEGIN a multi-step transaction before COMMIT/ROLLBACK, the UI must announce via aria-live that changes are 'pending, not yet saved', since a screen reader user has no visual cue that the database hasn't actually committed anything yet.
SEO Implications
- 1
Unclosed Transactions Can Silently Lock Rows and Slow Public Pages
A transaction that opens with BEGIN but never reaches COMMIT or ROLLBACK (e.g. due to an unhandled error) can hold row locks that make unrelated queries on public-facing pages wait, indirectly hurting Time to First Byte.
Best Practices
Always Pair BEGIN With a try/catch That Guarantees ROLLBACK on Error
In Node.js, wrap 'BEGIN' and 'COMMIT' inside a try block and call 'ROLLBACK' in the catch block, so any exception during the transaction automatically undoes partial changes instead of leaving the database in a half-finished state.
Never Run DROP DATABASE Without a Verified, Recent Backup
Unlike a transaction, DROP DATABASE destroys the entire database instantly and typically cannot be rolled back — confirm you're connected to the right server and that a backup exists before ever typing this command.
Frequent Bugs
A Node.js API crashes partway through a multi-step database operation, and the first UPDATE's changes stay permanently committed even though the second UPDATE never ran.
Without wrapping both statements in a transaction (BEGIN ... COMMIT), each DML statement commits independently the instant it runs. Wrap related statements in BEGIN/COMMIT and issue ROLLBACK in your catch block so a failure partway through undoes everything.
Real-World Examples
Transferring Funds Between Two Accounts Safely
A banking feature needed to debit one account and credit another as a single atomic operation, so a crash between the two updates could never lose money.
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 'alice';
UPDATE accounts SET balance = balance + 100 WHERE id = 'bob';
COMMIT;