DEV Community

Cover image for Building a Full-Stack App with Next.js & Prisma: Part 1 – Setting Up the Database Client
Ankit
Ankit

Posted on

Building a Full-Stack App with Next.js & Prisma: Part 1 – Setting Up the Database Client

0) Mental Model - What happens on a request?

  1. User hits a route → middleware.ts checks whether they’re logged in and whether the route is public/protected/auth.
  2. If sign-in is needed, user goes to /auth/sign-in and chooses Google or GitHub.
  3. NextAuth + PrismaAdapter look up the user; if new, create User + Account; if existing, link the provider.
  4. Callbacks enrich the JWT and session with id and role.
  5. Client now has session.user.id and session.user.role for RBAC and UI.

1) Database Client (Prisma) — lib/db.ts

import { PrismaClient } from "@prisma/client"

const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }

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

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

Enter fullscreen mode Exit fullscreen mode

At first glance, this may look a bit tricky. Let’s break it down.

import { PrismaClient } from "@prisma/client"
Enter fullscreen mode Exit fullscreen mode
  • PrismaClient is the main tool you use to talk to your database
  • Think of it like a “bridge” that connects your code with your database (MySQL, PostgreSQL, SQLite, etc.).
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }
Enter fullscreen mode Exit fullscreen mode
  • In Next.js (or any serverless environment), new instances of the code can spin up frequently.
  • If you create a new database client every time, you risk having too many open connections.
  • To prevent this, we attach Prisma to the global object (globalThis), so it can be reused.

This ensures that if Prisma is already created, we don’t create it again.

export const db = globalForPrisma.prisma || new PrismaClient()
Enter fullscreen mode Exit fullscreen mode
  • Here, we check:
    • If a Prisma instance already exists (globalForPrisma.prisma), use it.
    • Otherwise, create a new one (new PrismaClient()).

This is the key step that prevents multiple Prisma clients from being created unnecessarily.

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db
Enter fullscreen mode Exit fullscreen mode
  • In development mode, your app refreshes and hot-reloads often.
  • Without this line, Prisma would create a new connection each time, eventually causing errors like: “Too many connections”.
  • This line ensures the same db instance is reused during development.

In production, Next.js doesn’t hot-reload, so we don’t need this safeguard.

So Why Does This Matters

  • Prevents performance issues caused by too many connections.
  • Works well with Next.js serverless functions.
  • Shows professionalism: any recruiter or developer reviewing your code will see you understand real-world database issues.

Finally

This small snippet may look simple, but it solves a very common real-world problem.

Top comments (0)