A transaction groups several writes so they all succeed or all fail together. If any step throws, the database undoes everything as if none of it happened. Think of a bank transfer: money leaves one account and arrives in another. You never want one half to happen without the other.
How to use it
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
// $transaction hands you a scoped `tx` client; everything on it commits together
await prisma.$transaction(async (tx) => {
await tx.account.update({
where: { id: fromAccount },
data: { balance: { decrement: 100 } },
});
await tx.account.update({
where: { id: toAccount },
data: { balance: { increment: 100 } },
});
});
// If the second update throws, the first is rolled back automatically. Common reasons you may need one
- Any operation that writes to more than one row or table and must agree
- Moving a value from one place to another (transfers, inventory, balances)
- Steps where a partial result would leave your data in a broken state
If you're only doing a single write, you don't need an explicit transaction. One statement is already all-or-nothing.
Exercise
Node challenge · runs in your browser