advanced

Transactions

Keep business invariants correct across multiple data access calls with isolation, retries, and clear transaction scope.

ORM transactions group multiple reads and writes under one database transaction. Use them to protect business invariants—not as a default wrapper around every HTTP request.

					await db.transaction(async (tx) => {
  const balance = await tx.account.findForUpdate(id);
  if (balance.amount < transfer) throw new Error('insufficient');
  await tx.account.debit(id, transfer);
  await tx.account.credit(targetId, transfer);
});
				

On interviews: discuss scope, isolation anomalies, retries, outbox patterns for messages, and avoiding network I/O while holding locks.

Common pitfalls: long transactions increasing contention; payment or message calls inside a DB transaction; retrying without idempotency keys.

The trade-off is correctness guarantees versus lock time and connection pressure.

Checklist:

  • Define the invariant being protected.
  • Keep lock time short.
  • Plan retries and side effects.
  • Separate DB commit from external calls.