DEV Community

Farmin Farzin
Farmin Farzin

Posted on • Edited on • Originally published at farmin.dev

Have you ever accidentally delete all the table data with Prisma?

This not a story about a bug but rather a feature!

Have you ever used table.updateMany or table.deleteMany in your code? we have and it was something like this:

const deleteChildrenOfThatParent = await prisma.children.deleteMany({
  where: {
    parentEmail: {
      equal: parent.email,
    },
  },
})
Enter fullscreen mode Exit fullscreen mode

It was working great for a long time and you know what, we had TS checking the types too but somehow someday we lost all of our children data in the table.
We checked the database (Postgres) and we found out that at a certain time, all of the data has been wiped out! We blamed DevOps, hackers, AWS, ... but it was us not anyone else.

Finally, we figured out that we might had a situation that parent.email was undefined. But still we couldn't believe that deleteMany with a condition executed that. After some testing we were shocked but that was true and actually it made sense... our "where" clause made the code in a way that we deleted all the children only because of that undefined. we basically ran:

const deleteChildrenOfThatParent = await prisma.children.deleteMany({
  where: {},
  },
})
Enter fullscreen mode Exit fullscreen mode

What could have saved us though?

Retro

So we had a retro around it and there were some angry stakeholders there! We promised them that this would never happen again! first thing first we just found every updateMany and deleteMany functions and we bookmarked them. We could just put a condition before each one to check for undefined but this wasn't a permanent solution neither scalable one.
After some investigation, we found a great solution, yeah Prisma itself came to help :p

Prisma Middleware

So what we needed to implement was something in the lower layer on the prisma which could check all the mutations to make sure we're not removing data that we don't want to delete. Prisma Middleware is that thing YES!

we just implemented the middleware in a way that we check every query (mutations) and filter out the updateMany and deleteMany ones and make sure that there is a condition on them!

async function main() {
  prisma.$use(async (params, next) => {
    // Check incoming query type
    if (params.model === 'Post') {
      if (params.action === 'deleteMany' || params.action === 'updateMany') {
        //Check the Where clause in params.arg.where, if it's empty just return
      }
    }
    return next(params)
  })
Enter fullscreen mode Exit fullscreen mode

Top comments (0)