Managing Transactions

1. Using Interactive Transactions

await prisma.$transaction(async (tx) => {
  const from = await tx.account.update({ where: { id: 1 }, data: { balance: { decrement: 100 } } });
  if (from.balance < 0) throw new Error("Insufficient funds");
  await tx.account.update({ where: { id: 2 }, data: { balance: { increment: 100 } } });
}, { timeout: 10_000, maxWait: 5_000, isolationLevel: "Serializable" });
OptionDetail
timeoutMax ms for whole transaction
maxWaitWait for a connection
isolationLevelPer-transaction isolation

2. Creating Sequential Transactions

const [user, posts] = await prisma.$transaction([
  prisma.user.create({ data: { email } }),
  prisma.post.createMany({ data: items })
]);
AspectDetail
AtomicAll or none
No conditional logicPromises declared up front

3. Implementing Nested Writes

PatternDetail
Single callNested create/update wraps in implicit transaction
Cross-modelUse $transaction explicitly

4. Using Transaction Isolation Levels

LevelPG / MySQL
ReadUncommittedLowest, may see uncommitted
ReadCommittedDefault for PG
RepeatableReadDefault for MySQL
SerializableHighest; conflicts retried

5. Handling Transaction Rollbacks

TriggerEffect
Thrown errorRolls back
TimeoutRolls back
tx.$rollback()Not exposed; throw to abort

6. Setting Transaction Timeout

OptionDetail
Default5000ms (interactive), unbounded (sequential)
GlobalSet via transactionOptions on client

7. Using Idempotent Operations

PatternUse
upsertSafe retry
createMany + skipDuplicatesIdempotent bulk insert
Unique tokensIdempotency keys per request

8. Implementing Optimistic Concurrency

const res = await prisma.product.updateMany({
  where: { id, version },
  data: { price, version: { increment: 1 } }
});
if (res.count === 0) throw new Error("Concurrent modification");
AspectDetail
Version columnIncrement on every write
ConflictupdateMany returns 0

9. Avoiding Long-Running Transactions

TipDetail
Short bodyDon't call external APIs inside
Batch outsidePre-compute then write
Connection blockingLong tx holds a pool slot

10. Handling Transaction Errors

ErrorAction
P2028Transaction timeout — retry
P2034Write conflict (serializable) — retry
GenericLog + abort