# How to use Prisma

> Learn how to set up modern Prisma ORM with PostgreSQL, define a model, create migrations, generate Prisma Client, and run CRUD queries in a Next.js app.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2021-07-07 | Updated: 2026-07-18 | Topics: [Database](https://flaviocopes.com/tags/database/) | Canonical: https://flaviocopes.com/prisma/

Prisma is an ORM for working with databases from TypeScript and JavaScript.

You define models in a Prisma schema, create database migrations from those models, and generate a type-safe client for queries.

This guide uses PostgreSQL and a Next.js TypeScript application. The same workflow also works outside Next.js, but the database driver and application integration can differ.

## Install Prisma

From your application directory, install the Prisma CLI and PostgreSQL types as development dependencies:

```bash
npm install --save-dev prisma @types/pg
```

Install Prisma Client, the PostgreSQL driver adapter, and its runtime dependencies:

```bash
npm install @prisma/client @prisma/adapter-pg pg dotenv
```

Initialize Prisma:

```bash
npx prisma init \
  --datasource-provider postgresql \
  --output ../generated/prisma
```

Current Prisma projects use the `prisma-client` generator with an explicit output directory. Initialization creates:

- `prisma/schema.prisma`
- `prisma.config.ts`
- `.env`
- supporting ignore rules

See the current [`prisma init` reference](https://docs.prisma.io/docs/cli/init) before copying initialization output from an older project.

## Configure the database connection

Put the PostgreSQL connection string in `.env`:

```text
DATABASE_URL="postgresql://user:password@localhost:5432/cars"
```

Do not commit this file when it contains real credentials.

`prisma.config.ts` reads the connection URL and tells Prisma where to find the schema and migrations:

```ts
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config'

export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: {
    path: 'prisma/migrations'
  },
  datasource: {
    url: env('DATABASE_URL')
  }
})
```

Use a separate database and credentials for local development. Production credentials belong in the deployment platform's secret or environment-variable settings.

## Define a model

Open `prisma/schema.prisma`:

```prisma
generator client {
  provider = "prisma-client"
  output   = "../generated/prisma"
}

datasource db {
  provider = "postgresql"
}

model Car {
  id        Int      @id @default(autoincrement())
  brand     String
  model     String
  createdAt DateTime @default(now())
  bought    Boolean  @default(false)
}
```

The `Car` model becomes a database table.

`id` is its primary key and receives an automatically increasing value. `createdAt` defaults to the current time, and `bought` defaults to `false`.

The [Prisma schema reference](https://www.prisma.io/docs/orm/reference/prisma-schema-reference) documents field types, attributes, relations, indexes, and database-specific behavior.

## Create the first migration

Create and apply a development migration:

```bash
npx prisma migrate dev --name init
```

Then generate Prisma Client:

```bash
npx prisma generate
```

Current Prisma versions do not automatically run `prisma generate` after `prisma migrate dev`, so keep the two steps explicit.

Commit the generated SQL migration in `prisma/migrations/`. Do not edit the live production database by running `migrate dev` against it.

In a deployment pipeline, apply committed migrations with:

```bash
npx prisma migrate deploy
```

The [`migrate dev` documentation](https://www.prisma.io/docs/cli/migrate/dev) explains its development-only shadow database workflow.

## Create one Prisma Client

Create `lib/prisma.ts`:

```ts
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from '../generated/prisma/client'

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

const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL!
})

const prisma =
  globalForPrisma.prisma ??
  new PrismaClient({
    adapter
  })

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = prisma
}

export default prisma
```

Reusing the client through `globalThis` prevents Next.js hot reloads from creating many connection pools during development.

Use Prisma only in server-side code. Do not import the client into a Client Component or browser bundle.

Prisma's [Next.js guide](https://docs.prisma.io/docs/guides/frameworks/nextjs) shows the current generated-client and driver-adapter setup.

## Create a record

Prisma's create operations receive values inside `data`:

```ts
const car = await prisma.car.create({
  data: {
    brand: 'Ford',
    model: 'Fiesta'
  }
})
```

## Read records

Retrieve every car:

```ts
const cars = await prisma.car.findMany()
```

Filter the query:

```ts
const cars = await prisma.car.findMany({
  where: {
    brand: 'Ford'
  },
  orderBy: {
    createdAt: 'desc'
  }
})
```

Find one car by its unique ID:

```ts
const car = await prisma.car.findUnique({
  where: {
    id: 1
  }
})
```

`findUnique()` returns `null` when no matching record exists. Handle that case before using the result.

## Update a record

```ts
const car = await prisma.car.update({
  where: {
    id: 1
  },
  data: {
    bought: true
  }
})
```

`update()` throws if the record does not exist. Choose `updateMany()` or handle the error when absence is expected.

## Delete a record

```ts
await prisma.car.delete({
  where: {
    id: 1
  }
})
```

Validate authorization before updating or deleting data. A type-safe query is not automatically an authorized one.

## Start from an existing database

If the database already has tables, introspect it:

```bash
npx prisma db pull
npx prisma generate
```

Review the generated schema before building on it. Database names, unsupported features, and relation conventions may need manual adjustments.

If you want to compare schema formats, the [schema converter](https://flaviocopes.com/tools/schema-converter/) translates between SQL, Prisma, and Drizzle.

## Keep generated code current

Run `npx prisma generate` after changing the schema, changing generator settings, or pulling schema changes from another branch.

Many deployment systems cache dependencies, so add generation to the build or install workflow when required:

```json
{
  "scripts": {
    "postinstall": "prisma generate"
  }
}
```

Prisma's [client generation guide](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client) explains when generated code must be refreshed.
