Labsco
prisma logo

prisma-client-api-transactions

✓ Official8

by prisma · part of prisma/cursor-plugin

Transactions. Reference when using this Prisma feature.

🔥🔥🔥✓ VerifiedFreeQuick setup
🧩 One of 7 skills in the prisma/cursor-plugin package — works on its own, and pairs well with its siblings.

Transactions. Reference when using this Prisma feature.

Inspect the full instructions your agent will receiveExpand

This is the exact playbook injected into your agent when the skill activates — shown here so you can audit it before installing. You don't need to read it to use the skill.

by prisma

Transactions. Reference when using this Prisma feature. npx skills add https://github.com/prisma/cursor-plugin --skill prisma-client-api-transactions Download ZIPGitHub8

Transactions

Execute multiple operations atomically.

Sequential Transactions

Array of operations executed in order:

Copy & paste — that's it
const [user, post] = await prisma.$transaction([
 prisma.user.create({ data: { email: '[email protected]' } }),
 prisma.post.create({ data: { title: 'Hello', authorId: 1 } })
])

All or nothing

If any operation fails, all are rolled back:

Copy & paste — that's it
try {
 await prisma.$transaction([
 prisma.user.create({ data: { email: '[email protected]' } }),
 prisma.user.create({ data: { email: '[email protected]' } }) // Duplicate!
 ])
} catch (e) {
 // Both operations rolled back
}

Interactive Transactions

For complex logic and dependent operations:

Copy & paste — that's it
await prisma.$transaction(async (tx) => {
 // Decrement sender balance
 const sender = await tx.account.update({
 where: { id: senderId },
 data: { balance: { decrement: amount } }
 })
 
 // Check balance
 if (sender.balance {
 // operations
 },
 {
 maxWait: 5000, // Max wait to acquire lock (ms)
 timeout: 10000, // Max transaction duration (ms)
 isolationLevel: 'Serializable' // Isolation level
 }
)

Isolation levels

Level Description ReadUncommitted Lowest isolation, can read uncommitted changes ReadCommitted Only read committed changes RepeatableRead Consistent reads within transaction Serializable Highest isolation, serialized execution

Nested Writes

Automatic transactions for nested operations:

Copy & paste — that's it
// This is automatically a transaction
const user = await prisma.user.create({
 data: {
 email: '[email protected]',
 posts: {
 create: [
 { title: 'Post 1' },
 { title: 'Post 2' }
 ]
 },
 profile: {
 create: { bio: 'Hello!' }
 }
 }
})

Transaction Client

The tx parameter is a Prisma Client scoped to the transaction:

Copy & paste — that's it
await prisma.$transaction(async (tx) => {
 // Use tx instead of prisma
 await tx.user.create({ ... })
 await tx.post.create({ ... })
 
 // Can call methods
 const count = await tx.user.count()
})

OrThrow in Transactions

Use with interactive transactions:

Copy & paste — that's it
await prisma.$transaction(async (tx) => {
 // If not found, throws and rolls back entire transaction
 const user = await tx.user.findUniqueOrThrow({
 where: { id: 1 }
 })
 
 await tx.post.create({
 data: { title: 'New Post', authorId: user.id }
 })
})

Best Practices

Keep transactions short

Copy & paste — that's it
// Good - only DB operations in transaction
const data = prepareData() // Outside transaction
await prisma.$transaction(async (tx) => {
 await tx.user.create({ data })
})

Handle errors

Copy & paste — that's it
try {
 await prisma.$transaction(async (tx) => {
 // operations
 })
} catch (e) {
 if (e.code === 'P2002') {
 // Handle unique constraint violation
 }
 throw e
}

Use appropriate isolation

Copy & paste — that's it
// Default is fine for most cases
await prisma.$transaction(async (tx) => {
 // operations
})

// Use Serializable for strict consistency
await prisma.$transaction(
 async (tx) => { /* operations */ },
 { isolationLevel: 'Serializable' }
)

Sequential vs Interactive

Feature Sequential Interactive Syntax Array Async function Dependent ops No Yes Conditional logic No Yes Performance Better More flexible Use case Simple batch Complex logic