Prisma error P2034 (Transaction Write Conflict or Deadlock) explained: what it means, why it happens, and how to fix it — with copy-paste code examples.
Wrap the interactive transaction body in a retry loop (3 attempts with backoff) - P2034 is transient by design. If that does not apply, keep transactions short: do validation and external calls before $transaction, not inside it — the full checklist is below.
Error code: P2034
Official name: Transaction Write Conflict or Deadlock
Service: Prisma
Transaction failed due to a write conflict or a deadlock. Please retry your transaction
for (let attempt = 0; attempt < 3; attempt++) {
try {
return await prisma.$transaction(async (tx) => {
/* business logic */
})
} catch (e) {
if (e.code !== 'P2034') throw e
if (attempt === 2) throw e
await new Promise((r) => setTimeout(r, 50 * 2 ** attempt))
}
}
P2034 is the documented signal to retry - exponential backoff avoids thundering-herd retries.
await prisma.post.updateMany({
where: { id, version: expectedVersion },
data: { title, version: { increment: 1 } },
})
// if count === 0 the row changed under you - reload and reapply
Guarding with a version column turns blind updates into detectable conflicts without DB-level retries.
Retry P2034 inside a small exponential-backoff helper; treat it as transient, never as a permanent failure.
async function withRetry(fn, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await fn()
} catch (e) {
if (e.code !== 'P2034' || i === attempts - 1) throw e
await delay(50 * 2 ** i)
}
}
}
Keep interactive transactions minimal and only touch the rows you must; external I/O belongs outside $transaction.
await prisma.$transaction(async (tx) => {
// only DB work here
await tx.account.update({ where: { id }, data: { balance: { decrement: amount } } })
await tx.account.update({ where: { id: otherId }, data: { balance: { increment: amount } } })
})
Most often this happens when two interactive transactions update the same row concurrently (lost-update race), or when transactions acquiring locks in opposite orders on two tables (classic deadlock).
Wrap the interactive transaction body in a retry loop (3 attempts with backoff) - P2034 is transient by design.
This page documents fixes for: nestjs, prisma-client.
Recommendations are editorial — DB Error Reference takes no payment or affiliate fees for tool listings.
This page is based on the official Prisma documentation linked below and adds practical troubleshooting guidance on top.