Connect to databases using ORMs like Prisma, handle migrations, and query data safely.
npm install @prisma/client
npm install -D prisma
npx prisma initDATABASE_URL="postgresql://user:password@localhost:5432/mydb"// lib/prisma.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = global as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma =
globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== "production") {
globalForPrisma.prisma = prisma;
}// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
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
}npx prisma migrate dev --name add_posts# List all migrations
npx prisma migrate status
# Replay all migrations (for new databases)
npx prisma migrate deployimport { prisma } from "@/lib/prisma";
export default async function Users() {
const users = await prisma.user.findMany();
return <div>{users.map(u => <div>{u.name}</div>)}</div>;
}const user = await prisma.user.findUnique({
where: { email: "alice@example.com" }
});const newUser = await prisma.user.create({
data: {
email: "bob@example.com",
name: "Bob"
}
});const updated = await prisma.user.update({
where: { id: 1 },
data: { name: "Robert" }
});const users = await prisma.user.findMany({
include: { posts: true }
});const published = await prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: "desc" },
take: 10
});const [user, post] = await prisma.$transaction([
prisma.user.create({ data: { email: "test@example.com" } }),
prisma.post.create({ data: { title: "Hello", authorId: 1 } })
]);// app/api/posts/route.ts
export async function POST(request) {
const data = await request.json();
const post = await prisma.post.create({ data });
return Response.json(post);
}Export a single PrismaClient instance from a dedicated module and cache it on the global object during development to survive hot reloads. In production, one instance per serverless function lifecycle is fine as long as you're not instantiating it inside request handlers on every call.
Yes — Server Components run exclusively on the server, so you can import your Prisma client and call it directly without an API route. Just ensure you never pass the client or raw query results containing sensitive fields to Client Components.
Use migrate dev during local development — it generates migration files and applies them, and can reset the database if needed. Use migrate deploy in CI/CD and production — it applies existing migration files without generating new ones or altering data.
Add a seed script to prisma/seed.ts and register it under the prisma.seed key in package.json, then run npx prisma db seed. Prisma migrate dev will also call the seed script automatically after resetting the database.
Prisma handles most CRUD and relational queries cleanly, but for heavy aggregations or queries that generate inefficient SQL you can drop down to prisma.$queryRaw with tagged template literals, which still protects against SQL injection through parameterization.