iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Prisma ORM

Prisma: type-safe ORM for Node. Schema-first, auto-generated client, migrations, and the patterns for production.

Node — Prisma

EXAMPLE
// ===== Install =====
npm install prisma --save-dev
npm install @prisma/client
npx prisma init

// ===== Schema (prisma/schema.prisma) =====
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  posts     Post[]
  createdAt DateTime @default(now())
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  authorId  Int
  author    User     @relation(fields: [authorId], references: [id])

  @@index([authorId, published])
}

// ===== Migrate =====
npx prisma migrate dev --name init       // creates SQL migration + applies it
npx prisma migrate deploy                // production: apply pending migrations
npx prisma db push                        // dev only: sync without migration

// ===== Generate client =====
npx prisma generate
// Generates types in node_modules/.prisma/client

// ===== Use =====
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();

// Create
const user = await prisma.user.create({
  data: { email: 'a@x.io', name: 'Alex', posts: { create: [{ title: 'Hi' }] } },
});

// Read
const u = await prisma.user.findUnique({
  where: { email: 'a@x.io' },
  include: { posts: true },
});

const users = await prisma.user.findMany({
  where: { posts: { some: { published: true } } },
  orderBy: { createdAt: 'desc' },
  take: 20,
});

// Update
await prisma.post.update({
  where: { id: 1 },
  data: { published: true },
});

// Delete
await prisma.post.delete({ where: { id: 1 } });

// Transactions
const [u, p] = await prisma.$transaction([
  prisma.user.create({ data: { email: 'b@x.io' } }),
  prisma.post.create({ data: { title: 'New', authorId: 1 } }),
]);

// Interactive transactions
await prisma.$transaction(async (tx) => {
  const u = await tx.user.create({ data: { email: 'c@x.io' } });
  await tx.post.create({ data: { title: 'X', authorId: u.id } });
});

// Raw SQL (when you need it)
const result = await prisma.$queryRaw\`SELECT * FROM "User" WHERE email = ${email}\`;

// ===== Connection pooling =====
// Long-lived processes: one PrismaClient per app
// Serverless: use PgBouncer or Prisma Accelerate

// In Next.js dev:
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;

// ===== Prisma Studio =====
npx prisma studio
// Visual DB browser at http://localhost:5555

// ===== Patterns =====
// - Schema-first; migrations in source control
// - One PrismaClient per process
// - include/select for explicit field selection
// - Transactions for multi-write atomicity
// - Raw SQL for hot queries Prisma's planner does not nail

// ===== Pitfalls =====
// - Forgetting to run prisma generate after schema changes
// - Many PrismaClients in dev (hot reload) -> connection exhaustion
// - Select * by accident with include everywhere
// - Not using PgBouncer / Accelerate in serverless

Why it matters

Prisma is the modern TypeScript-first ORM: schema, migrate, generate, use. The types come free; the migrations live in source control; the client is one per process. Pair with PgBouncer / Accelerate for serverless and the production story is solid.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// schema.prisma defines models; client is generated.
const users = await prisma.user.findMany({ where: { active: true } });
const u = await prisma.user.create({ data: { name: 'Ada' } });
Try it Yourself »

Discussion

Loading…