1. Project Initialization
Start by setting up your Node.js environment with TypeScript. We use tsx for modern, fast execution.
mkdir prisma-postgres-2025
cd prisma-postgres-2025
npm init -y
npm install typescript tsx @types/node --save-dev
npx tsc --init
2. Install Prisma and PostgreSQL Driver
In 2025, it is highly recommended to install the official PostgreSQL adapter for better performance in serverless and edge environments.
npm install prisma --save-dev
npm install @prisma/client @prisma/adapter-pg pg
3. Initialize Prisma
Run the following to generate your boilerplate. This creates the prisma/schema.prisma file and a .env file.
npx prisma init --datasource-provider postgresql
4. Configure Your Connection
Open your .env file. PostgreSQL connection strings follow this format:
# Format: postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=public
DATABASE_URL="postgresql://postgres:mypassword@localhost:5432/mydb?schema=public"
5. Define Your Modern Schema
In prisma/schema.prisma, define your models. As Allyn noted, these act as the "proxy" to your database.
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
6. Apply Migrations
Use Prisma Migrate to push your schema to PostgreSQL. This creates the actual tables and generates your type-safe client.
npx prisma migrate dev --name init
7. Instantiate the Client (Singleton Pattern)
To prevent "Too many connections" errors in PostgreSQL (especially during development with hot-reloading), use this singleton pattern:
// db.ts
import { PrismaClient } from '@prisma/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
8. Performing CRUD Operations
Now you can write fully type-safe queries. Prisma handles the PostgreSQL JOINs and relations automatically.
import { prisma } from './db'
async function run() {
// Create a user and a post in one transaction
const user = await prisma.user.create({
data: {
email: 'hello@dev.to',
name: 'Dev Reader',
posts: {
create: { title: 'Learning Prisma in 2025' }
}
}
})
// Read: Fetch all users and include their posts
const allUsers = await prisma.user.findMany({
include: { posts: true }
})
console.log(JSON.stringify(allUsers, null, 2))
}
run()
🚀 What’s New for PostgreSQL in 2025?
- Rust-Free Engine: Prisma 6/7 moved to a TypeScript-based engine. This means faster cold starts and smaller Docker images when deploying your Postgres app.
-
TypedSQL: You can now write raw SQL in
.sqlfiles, and Prisma will generate TypeScript types for them—giving you the power of raw SQL with the safety of an ORM. -
Prisma Studio: As mentioned by Allyn, run
npx prisma studioto get a visual dashboard of your PostgreSQL data. It’s the easiest way to debug your records without a separate DB manager.
Pro-Tip: If you are using a hosted PostgreSQL provider like Supabase or Neon, ensure you use their "Connection Pooling" strings in your .env to handle high traffic efficiently.
Top comments (0)