Middlewares act as query-level lifecycle hooks, which allow you to perform an action before or after a query runs. Use the prisma.$use method to add middlewares:

const prisma = new PrismaClient()
// Middleware 1
prisma.$use(async (params, next) => {
// Manipulate params here
const result = await next(params);
// See results here
return result;
})
// Middleware 2
prisma.$use(async (params, next) => {
// Manipulate params here
const result = await next(params);
// See results here
return result;
})
// Queries here

Use cases for middleware include:

Examples

Running order

If you have multiple middlewares, the running order for each separate query is:

  1. All logic before await next(params)
  2. All logic after await next(params)
const prisma = new PrismaClient()
prisma.$use(async (params, next) => {
console.log(params.args.data.title)
console.log('1')
const result = await next(params)
console.log('4')
return result
})
prisma.$use(async (params, next) => {
console.log('2')
const result = await next(params)
console.log('3')
return result
})
const create = await prisma.post.create({
data: {
title: 'Welcome to Prisma Day 2020',
},
})
const create2 = await prisma.post.create({
data: {
title: 'How to Prisma!',
},
})

Output:

Welcome to Prisma Day 2020
1
2
3
4
How to Prisma!
1
2
3
4

Performance and appropriate use cases

Middleware executes for every query, which means that overuse has the potential to negatively impact performance. To avoid adding performance overheads:

  • Check the params.model and params.action properties early in your middleware to avoid running logic unnecessarily:

    prisma.$use(async (params, next) => {
    if (params.model == 'Post' && params.action == 'delete') {
    // Logic only runs for delete action and Post model
    }
    return next(params)
    })
  • Consider whether middleware is the appropriate solution for your scenario. For example:

    • If you need to populate a field, can you use the @default attribute?
    • If you need to set the value of a DateTime field, can you use the now() function or the @updatedAt attribute?
    • If you need to perform more complex validation, can you use a CHECK constraint in the database itself?
Edit this page on GitHub