Techtales.

How to Use Drizzle ORM with PostgreSQL in a Next.js 15 Project
TD
The Don✨Author
Aug 30, 2025
6 min read

How to Use Drizzle ORM with PostgreSQL in a Next.js 15 Project

Drizzle ORM is a type-safe, SQL-focused ORM for TypeScript that simplifies database modeling and queries with familiar SQL-like syntax. It integrates smoothly with PostgreSQL and modern frameworks like Next.js.

This means we can easily connect a Drizzle-powered Node.js based environment of a Next.js application to a running PostgreSQL database and then power the React side with Drizzle-based queries and server actions.

In this tutorial, we will learn how to:

  • Install & configure Drizzle for connecting PostgreSQL to Node.js in a Next.js application.
  • Declare Drizzle schema files with tables, schemas, partial queries, views, relations, and type definitions.
  • Generate migration files and perform migrations & seeding.
  • Use Drizzle for data fetching in a Next.js server-side.
  • Use Drizzle for database mutations from client-side forms with React Hook Form and Zod.
  • Use Drizzle Query APIs for performing relational queries that return related resources as nested objects.

 

Prerequisites

Before we begin, make sure you have the following:

  • Node.js 18+ installed
  • A running PostgreSQL instance (local or hosted)
  • Basic familiarity with Next.js App Router and TypeScript
  • The starter project cloned from the GitHub repository (use the prepare branch)

Overview of Drizzle ORM

Drizzle ORM wraps SQL in TypeScript, mirroring SQL syntax with strong type safety. It brings relational modeling, querying, and migrations into your codebase with a developer-friendly API. Unlike traditional ORMs, Drizzle stays close to SQL — so if you know SQL, you already know Drizzle.

Key features include:

  • Dialect-specific packages (pg-core for PostgreSQL, etc.)
  • Type-safe query building with select(), insert(), update(), delete()
  • A relational Query API for nested object fetching
  • First-class Zod integration via drizzle-zod
  • Migration tooling via drizzle-kit

Step 1: Install & Configure Drizzle

In your project root, install the required packages:

Next, create a drizzle.config.ts file at the root of your project:

And add your database credentials to a .env file:

Step 2: Define Drizzle Schema Files

Create the directory ./app/db/schema/. We'll separate schema definitions by resource to keep things clean and avoid circular dependency issues with relations.

invoices.schema.ts

customers.schema.ts

relations.ts

Keep relations in a separate file to avoid circular dependency issues:

index.ts

Step 3: Connect Drizzle to PostgreSQL

Create a PostgreSQL client at ./app/db/client.ts:

Then create the Drizzle instance at ./app/db/index.ts:

Step 4: Generate Migrations & Seed the Database

Add the following scripts to your package.json:

Generate migration files:

Run migrations to create the tables in PostgreSQL:

Create a ./app/db/seed.ts file to populate the database with sample data using drizzle-seed:

Then run:

Step 5: Server-Side Data Fetching with Drizzle

Now update ./app/lib/data.ts to replace mock data with real Drizzle queries. Since Next.js App Router pages are async React Server Components by default, we can query the database directly:

For cases where Drizzle's TypeScript API doesn't cover a specific SQL feature — such as PostgreSQL's CASE WHEN — you can use the sql template operator:

Step 6: Relational Queries with Drizzle Query API

For pages that need nested relational data, use the Drizzle Query API via db.query. This avoids manual join logic and returns related records as nested objects.

Fetching a single customer with their invoices:

Step 7: Database Mutations with Next.js Server Actions

For mutations, we use Next.js Server Actions with the "use server" directive. Drizzle provides insert(), update(), and delete() for this purpose.

Drizzle ORM strikes a great balance between the control of raw SQL and the convenience of a modern ORM. Its TypeScript-first design, tight Zod integration, and compatibility with Next.js App Router make it a compelling choice for building type-safe, database-backed applications in 2025 and beyond.

The completed code for this tutorial is available on the drizzle branch of the GitHub repository linked at the top of this post. Feel free to explore, fork, and extend it for your own projects.

0
0