Clarify when Prisma queries are run (PrismaPromise behavior)
See original GitHub issue@Sytten brought up a good point in Slack that we don’t really talk about when queries are executed.
In this example:
import { User } from '@prisma/client'
export default async (app: Application, { id }: DeleteInput): Promise<User> => {
  const operations: Promise<any>[] = []
  // Delete onboarding
  operations.push(app.prisma.onboarding.deleteMany({ where: { userId: id } }))
  // Delete availability application
  const availabilityApp = await app.models.availabilityApp.findOne({ userId: id })
  if (availabilityApp) {
    operations.push(
      app.prisma.availabilityTemplate.deleteMany({
        where: { appId: availabilityApp.id },
      }),
      app.prisma.availabilityApp.delete({ where: { id: availabilityApp.id } })
    )
  }
  // Delete user
  const user = await app.prisma.user.findOne({ where: { id } })
  operations.push(app.prisma.user.delete({ where: { id } }))
  // Execute all operations
  await app.prisma.transaction(operations)
  return user!
}
You might expect the operations to run in the order that they appear, but this is not the case. They run more like this:
await app.models.availabilityApp.findOne({ userId: id })
await app.prisma.user.findOne({ where: { id } })
// batched together at the end
app.prisma.onboarding.deleteMany({ where: { userId: id } })
app.prisma.availabilityTemplate.deleteMany({
  where: { appId: availabilityApp.id },
}),
app.prisma.availabilityApp.delete({ where: { id: availabilityApp.id } })
app.prisma.user.delete({ where: { id } })
This is because Prisma queries are then-ables, meaning they only execute when you call await or .then() or .catch(). This is called lazy evaluation. This is different then a regular promise which starts executing immediately. This would be called eager evaluation or immediate evaluation.
This was an understandable source of confusion for @Sytten because most libraries using promises eagerly evaluate. For example:
const fs = require('fs/promises')
fs.readFile("./test.txt") // starts reading the file immediately!
But in the Prisma client:
const deleteOperation = app.prisma.onboarding.deleteMany({ where: { userId: id } }) // doesn't do anything
// ...
deleteOperation.then() // now it executes
// or..
await deleteOperation // now it executes.
Issue Analytics
- State:
 - Created 3 years ago
 - Reactions:20
 - Comments:9 (3 by maintainers)
 
Top Results From Across the Web
Query optimization - Prisma
This guide describes ways to optimize query performance, debug performance issues, and how to tackle common performance issues such as the ...
Read more >Raw database access (Reference) - Prisma
Learn how you can send raw SQL and MongoDB queries to your database using the raw() methods from the Prisma Client API.
Read more >Transactions and batch queries (Reference) - Prisma
Sequential operations: pass an array of Prisma Client queries to be executed sequentially inside a transaction, using $transaction<R>(queries: PrismaPromise<R>[] ...
Read more >Prisma Client API (Reference)
Logs all queries run by Prisma. For relational databases this logs all SQL queries. Example: prisma:query SELECT "public"."User"."id" ...
Read more >Prisma Client
Note that queries will only run if used with await or chained with .then() . · The client methods are "thenable", they return...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

Maybe I’m misunderstanding the examples in this issue, but how would one do “fire-and-forget” queries?
Example: I have a simple API endpoint where some “post” data is returned. For each request, I also want to increment the view counter of that post. Something like:
I don’t care about the result of the
updatequery, so I also don’t want to wait for it at all, as otherwise each request for “post” data will have to wait until the “increment view” operation is finished first.There’s a similar discussion for this use case, but it’s from 2020, so I’m not sure if it is still relevant.
@shadoath Yes that should be faster, though in the transaction queries will be executed sequentially. Another option would be to use
Promise.all()orPromise.allSettled()to run all the queries at the same time, like