Best practices for using Prisma Client with Next.js
Problem
Many users have come across this warning while working with Next.js in development:
warn(prisma-client) There are already 10 instances of Prisma Client actively running.
There's a related discussion and issue for the same.
In development, the command next dev clears Node.js cache on run. This in turn initializes a new PrismaClient instance each time due to hot reloading that creates a connection to the database. This can quickly exhaust the database connections as each PrismaClient instance holds its own connection pool.
Solution
The solution in this case is to instantiate a single instance PrismaClient and save it on the globalThis object. Then we keep a check to only instantiate PrismaClient if it's not on the globalThis object otherwise use the same instance again if already present to prevent instantiating extra PrismaClient instances.
import { PrismaClient } from '@prisma/client'
const prismaClientSingleton = () => {
return new PrismaClient()
}
declare global {
var prisma: undefined | ReturnType<typeof prismaClientSingleton>
}
const prisma = globalThis.prisma ?? prismaClientSingleton()
export default prisma
if (process.env.NODE_ENV !== 'production') globalThis.prisma = prisma
You can extend Prisma Client using a Prisma Client extension by appending the $extends client method when instantiating Prisma Client as follows:
import { PrismaClient } from '@prisma/client'
const prismaClientSingleton = () => {
return new PrismaClient().$extends({
result: {
user: {
fullName: {
needs: { firstName: true, lastName: true },
compute(user) {
return `${user.firstName} ${user.lastName}`
},
},
},
},
})
}
After creating this file, you can now import the extended PrismaClient instance anywhere in your Next.js pages as follows:
// e.g. in `pages/index.tsx`
import prisma from './db'
export const getServerSideProps = async () => {
const posts = await prisma.post.findMany()
return { props: { posts } }
}
Next.js caching
When using Next.js, you may run into an issue where only stale data is returned from certain routes. In these cases, it's important to set the dynamic behavior of the route to "force-dynamic" so data is correctly returned from your Prisma Client queries.
You can add "force-dynamic" like this:
import { NextRequest, NextResponse } from 'next/server'
import prisma from './db'
export const dynamic = 'force-dynamic'
export async function GET(request: NextRequest, response: NextResponse) {
// your code would go here
}