Troubleshooting

Next.js

Best practices and troubleshooting for using Prisma ORM with Next.js applications

Prisma ORM and Next.js form a powerful combination for building modern web applications. This guide covers best practices, common issues, and solutions.

Best practices for using Prisma Client in development

Avoid multiple Prisma Client instances

When developing a Next.js application, one common issue is accidentally creating multiple instances of the Prisma Client. This often occurs due to Next.js's hot-reloading feature in development.

Why this happens

Next.js's hot-reloading feature reloads modules frequently to reflect code changes instantly. However, this can lead to multiple instances of Prisma Client being created, which consumes resources and might cause unexpected behavior.

To avoid this, create a single Prisma Client instance by using a global variable:

// lib/prisma.ts
import { PrismaClient } from "../prisma/generated/client";

const globalForPrisma = global as unknown as { prisma: PrismaClient };

export const prisma = globalForPrisma.prisma || new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

Using this approach ensures that only one instance of Prisma Client exists, even during hot-reloading in development.

Setting Up Prisma ORM in a Monorepo

Challenges of using Prisma ORM in monorepos

Monorepos allow multiple projects to share code and dependencies, making them a popular choice for modern development. However, using Prisma ORM in a monorepo can present challenges related to dependency resolution and schema management.

Key issues

  1. Dependency Resolution: Multiple packages in a monorepo might lead to conflicts if they use different version of Prisma ORM.
  2. Schema Centralization: Managing a single Prisma Schema across multiple projects can be complex.

Best practices for monorepo integration

  • Centralize the Prisma Schema: Place the schema.prisma file in a shared package, such as @myorg/db, to ensure consistency.

  • Use a custom output directory for generated client: Define a custom output directory for the generated Prisma Client to maintain consistency across packages.

  • Install dependencies in the root: To prevent version conflicts, install Prisma ORM at the root of the monorepo.

  • Use NPM Scripts for Generation:

    {
      "scripts": {
        "prisma:generate": "prisma generate --schema=./packages/db/schema.prisma"
      }
    }

Dynamic usage of Prisma Client in Next.js

Handling dynamic scenarios

Dynamic use cases, such as working with tenant-specific databases, require additional consideration when using Prisma ORM with Next.js.

Problem

Each tenant might have its own database, necessitating the creation of separate Prisma Clients at runtime. This can be complex in Next.js due to its hybrid rendering model.

Solution

Use a factory function to dynamically create Prisma Clients based on tenant-specific configurations:

// lib/prismaDynamic.ts
import { PrismaClient } from "../prisma/generated/client";

type TenantConfig = {
  databaseUrl: string;
};

export function createPrismaClient(config: TenantConfig): PrismaClient {
  return new PrismaClient({
    datasources: {
      db: {
        url: config.databaseUrl,
      },
    },
  });
}

Ensure that you manage the lifecycle of dynamically created Prisma Clients to avoid resource exhaustion.

Vercel build dependency caching

Problem

If you deploy an application using Prisma ORM to Vercel, you may run into the following error message on deployment:

Prisma has detected that this project was built on Vercel, which caches dependencies.
This leads to an outdated Prisma Client because Prisma's auto-generation isn't triggered.
To fix this, make sure to run the `prisma generate` command during the build process.

Learn how: https://pris.ly/d/vercel-build

This occurs because Vercel caches the dependencies of your project until one of those dependencies changes. Prisma ORM uses a postinstall hook to generate Prisma Client when dependencies are installed. Because Vercel uses cached modules, this postinstall hook never gets run in subsequent deployments after the initial deployment.

Solution

This issue can be solved by explicitly generating Prisma Client on every deployment. Running prisma generate before each deployment will ensure Prisma Client is up-to-date.

Within the scripts section of your project's package.json file, add prisma generate to the postinstall script:

{
  "scripts": {
    "postinstall": "prisma generate"
  }
}

Option 2: Add to build script

Prepend prisma generate to your build command:

{
  "scripts": {
    "build": "prisma generate && <actual-build-command>"
  }
}

Option 3: Vercel UI build settings

Within your project's dashboard, go to Settings > General > Build & Development Settings and prepend prisma generate to the Build Command field.

Netlify build dependency caching

Problem

If you deploy an application using Prisma ORM to Netlify, you may encounter a similar caching error:

Prisma has detected that this project was built on Netlify, which caches dependencies.
This leads to an outdated Prisma Client because Prisma's auto-generation isn't triggered.
To fix this, make sure to run the `prisma generate` command during the build process.

Learn how: https://pris.ly/d/netlify-build

Solution

The same solutions apply as for Vercel:

{
  "scripts": {
    "postinstall": "prisma generate"
  }
}

Option 2: Add to build script

{
  "scripts": {
    "build": "prisma generate && <actual-build-command>"
  }
}

Option 3: Netlify UI build settings

Within your project's dashboard, go to Site Settings > Build & deploy > Continuous deployment > Build settings and prepend prisma generate to the Build command field.

On this page