Interview frequency: …
Short answer
Reserve a specific client from the pool, run BEGIN and the operations, then COMMIT on success or ROLLBACK in a catch block.
Explanation
A transaction guarantees Atomicity in ACID: either every change succeeds or all of them are rolled back. It is essential to use the same Dedicated Client for every operation in a transaction, because pool.query() distributes operations across different connections and completely breaks the transaction.
Code example
const client = await pool.connect();
try {
await client.query("BEGIN");
await client.query("UPDATE accounts SET balance = balance - 100 WHERE id = $1", [from]);
await client.query("UPDATE accounts SET balance = balance + 100 WHERE id = $1", [to]);
await client.query("COMMIT");
} catch (e) {
await client.query("ROLLBACK");
throw e;
} finally {
client.release(); // return the dedicated connection to the pool
}Common mistakes
- Running BEGIN and COMMIT directly through pool.query instead of a reserved, dedicated client.