Middleware
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 1prisma.$use(async (params, next) => {// Manipulate params hereconst result = await next(params);// See results herereturn result;})// Middleware 2prisma.$use(async (params, next) => {// Manipulate params hereconst result = await next(params);// See results herereturn result;})// Queries here
Use cases for middleware include:
- Setting or overwriting a field value - for example, setting the context language of a blog post comment
- Validating input data - for example, check user input for inappropriate language via an external service
- Intercept a
delete
query and change it to anupdate
in order to perform a soft delete - Log the time taken to perform a query
Examples
Running order
If you have multiple middlewares, the running order for each separate query is:
- All logic before
await next(params)
- 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 20201234How to Prisma!1234
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
andparams.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 thenow()
function or the@updatedAt
attribute? - If you need to perform more complex validation, can you use a
CHECK
constraint in the database itself?
- If you need to populate a field, can you use the