Overview

A database transaction refers to a sequence of read/write operations that are guaranteed to either succeed or fail as a whole.

Transactions are a great tool since they allow developers to disregard a number of potential concurrency problems that can occur when a database processes multiple operations in a short amount of time. Developers take advantage of the safety guarantees provided by the database by wrapping the operations in a transaction.

These guarantees are often summarized using the ACID acronym:

  • Atomic: Ensures that either all or none operations of the transactions succeed. The transaction is either committed successfully or aborted and rolled back.
  • Consistent: Ensures that the states of the database before and after the transaction are valid (i.e. any existing invariants about the data are maintained).
  • Isolated: Ensures that concurrently running transactions have the same effect as if they were running in serial.
  • Durability: Ensures that after the transaction succeeded, any writes are being stored persistently.

While there's a lot of of ambiguity and nuance to each of these properties (e.g. consistency could actually be considered an application-level responsibility rather than a database property or isolation is typically guaranteed in terms of stronger and weaker isolation levels), overall they serve as a good high-level guideline for expectations developers have when thinking about database transactions.

"Transactions are an abstraction layer that allows an application to pretend that certain concurrency problems and certain kinds of hardware and software faults don’t exist. A large class of errors is reduced down to a simple transaction abort, and the application just needs to try again." Designing Data-Intensive Applications, Martin Kleppmann

How Prisma Client supports transactions today

Prisma Client provides a data access API to read and write data from a database. For relational databases, Prisma Client's API abstracts over SQL where transactions are a common feature.

While Prisma Client doesn't allow for the same flexibility a SQL-level transaction provides, it covers the vast majority of use cases developers have for transactions with nested writes.

A nested write lets you perform a single Prisma Client API call with multiple operations that touch multiple related records, for example creating a user together with a post or updating an order together with an invoice. When a nested write is performed, Prisma Client ensures that it will either succeed or fail as a whole.

Here are examples for nested writes in the Prisma Client API:

1// Create a new user with two posts in a
2// single transaction
3const newUser: User = await prisma.user.create({
4 data: {
5 email: 'alice@prisma.io',
6 posts: {
7 create: [
8 { title: 'Join the Prisma Slack on https://slack.prisma.io' },
9 { title: 'Follow @prisma on Twitter' },
10 ],
11 },
12 },
13})
1// Change the author of a post in a single transaction
2const updatedPost: Post = await prisma.post.update({
3 where: { id: 42 },
4 data: {
5 author: {
6 connect: { email: 'alice@prisma.io' },
7 },
8 },
9})

Bulk operations (experimental)

Pre-requisites

You must activate the transactionApi feature flag in your schema.prisma file as follows:

1generator client {
2 provider = "prisma-client-js"
3 previewFeatures = ["transactionApi"]
4}

Once done, generate the client using npx prisma generate.

The transaction API

The following example will execute multiple operations within a transaction:

1const write1 = prisma.user.create()
2const write2 = prisma.post.create()
3const write3 = prisma.profile.create()
4
5await prisma.$transaction([write1, write2, write3])

Instead of immediately awaiting the result of each operation when it's performed, the operation itself is stored in a variable first which later is submitted to the database via a method called transaction. Prisma Client will ensure that either all three create-operations or none of them succeed.

Join the conversation on GitHub

If you'd like to see transactions supported in the future, please join the discussion on GitHub.

Edit this page on Github