Script Valley
REST API Development: Beginner to Production
Database Integration with PostgreSQL and PrismaLesson 5.3

Database transactions in Prisma — when and how to use them

ACID transactions, prisma.$transaction, sequential vs interactive transactions, rollback on error, use cases, avoiding partial updates

Database Transactions with Prisma

A transaction groups multiple database operations into one atomic unit — either all succeed or all roll back. Use transactions any time two or more writes must stay consistent.

Sequential Transactions

// Both operations execute atomically
const [debit, credit] = await prisma.$transaction([
  prisma.account.update({ where: { id: 1 }, data: { balance: { decrement: 100 } } }),
  prisma.account.update({ where: { id: 2 }, data: { balance: { increment: 100 } } })
]);

Interactive Transactions (with rollback logic)

await prisma.$transaction(async (tx) => {
  const sender = await tx.account.findUnique({ where: { id: 1 } });

  if (sender.balance < 100) {
    throw new Error('Insufficient funds'); // automatically rolls back
  }

  await tx.account.update({ where: { id: 1 }, data: { balance: { decrement: 100 } } });
  await tx.account.update({ where: { id: 2 }, data: { balance: { increment: 100 } } });
});

Use interactive transactions when you need to read data and make decisions inside the transaction. Throwing any error inside the callback automatically triggers a rollback. Sequential transactions are simpler but cannot branch based on read results. Avoid long transactions — they hold locks and degrade throughput.

Up next

N+1 query problem in APIs and how to fix it with Prisma

Sign in to track progress