Skip to main content
Advertisement

15.1 Prisma Introduction — The Standard TypeScript ORM

What is Prisma?

Prisma is a next-generation ORM (Object-Relational Mapper) for TypeScript. Define your data model in a schema file, and it auto-generates a type-safe client.

Prisma Components:
- Prisma Schema: Define data models (.prisma file)
- Prisma Client: Auto-generated type-safe query builder
- Prisma Migrate: Schema-based DB migrations
- Prisma Studio: Data visualization GUI

Installation and Initialization

npm install prisma @prisma/client
npx prisma init # Creates prisma/schema.prisma and .env

Environment Variable

# .env
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"

Basic Schema

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

datasource db {
provider = "postgresql" // mysql, sqlite, mongodb, etc.
url = env("DATABASE_URL")
}

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

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

model Profile {
id Int @id @default(autoincrement())
bio String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}

model Tag {
id Int @id @default(autoincrement())
name String @unique
posts Post[]
}

Running Migrations

# Create and apply migration
npx prisma migrate dev --name init

# Apply production migrations
npx prisma migrate deploy

# Regenerate Prisma Client (after schema changes)
npx prisma generate

# Launch Prisma Studio
npx prisma studio

Basic Prisma Client Usage

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
// Connection is managed automatically

// Create user
const user = await prisma.user.create({
data: {
email: 'alice@example.com',
name: 'Alice',
},
})
console.log(user)
// { id: 1, email: 'alice@example.com', name: 'Alice', ... }
}

main()
.catch(console.error)
.finally(async () => {
await prisma.$disconnect()
})

Field Types Reference

model Example {
// ID types
id Int @id @default(autoincrement())
uuid String @id @default(uuid())
cuid String @id @default(cuid())

// Scalar types
name String
age Int
score Float
isActive Boolean @default(true)
data Json
bytes Bytes
createdAt DateTime @default(now())

// Optional field
bio String?

// Default values
role Role @default(USER)
count Int @default(0)

// Indexes
@@index([name])
@@unique([email, tenantId])
}

enum Role {
ADMIN
USER
GUEST
}

Pro Tips

Prisma Client Singleton Pattern

// lib/prisma.ts
import { PrismaClient } from '@prisma/client'

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

export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
})

// Prevent connection leaks during hot reload in development
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma
}

Prisma Accelerate (Edge Caching)

import { PrismaClient } from '@prisma/client/edge'
import { withAccelerate } from '@prisma/extension-accelerate'

const prisma = new PrismaClient().$extends(withAccelerate())

// Set cache TTL
const users = await prisma.user.findMany({
cacheStrategy: { ttl: 60 }, // 60 second cache
})
Advertisement