Prisma ORM 8 is here.Read the docs

The data contract

The data contract is the one description of your data model and how it is stored. Prisma ORM types your queries, plans your migrations, and checks your database against it.

Every Prisma ORM project has one description of its data: the models, their fields, and how they map to database tables. That description is the data contract, the contract.prisma file that replaced schema.prisma. For example, a blog's contract declares a User and a Post, the fields each one has, and how they relate. You author it in PSL, the Prisma Schema Language, the same language as schema.prisma:

src/prisma/contract.prisma
// use prisma-8

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

model Post {
  id     Int    @id @default(autoincrement())
  title  String
  userId Int
  user   User   @relation(fields: [userId], references: [id])
}

npx prisma orm init writes the first line, // use prisma-8, into every .prisma contract. The CLI does not need this line. The VS Code extension does, so keep it. A contract.ts file needs no header line.

npx prisma contract emit turns this file into two files that the CLI and your application read: contract.json and contract.d.ts. Your queries are type-checked against the contract, migrations are planned as changes to it, and npx prisma db verify checks a live database against it.

Why a contract

Your contract compiles to two plain files you can open and read. contract.json describes your models, how they are stored, and the database features they need. contract.d.ts holds the TypeScript types derived from it. You can read both files in a code review and hand them to tools and coding agents.

npx prisma db migrate records in your database which contract it applied. The first time db runs a query it checks that record and logs a warning on a mismatch. To fail instead, run npx prisma db verify in a deploy check.

How it works

A Prisma ORM project declares one contract file in prisma.config.ts:

prisma.config.ts
import "dotenv/config";
import { definePrismaConfig } from "prisma/config";
import { defineConfig as ormConfig } from "@prisma/orm-postgres/config";

export default definePrismaConfig({
  orm: ormConfig({
    contract: "./src/prisma/contract.prisma",
    db: {
      connection: process.env["DATABASE_URL"]!,
    },
  }),
});

definePrismaConfig holds the whole config: which contract file to use and how to reach your database. Your connection string is in prisma.config.ts now, and the contract has no datasource block. npx prisma orm init writes .env.example, and your DATABASE_URL goes in .env. @prisma/orm-postgres/config exports defineConfig. The example renames it to ormConfig on import. The packages are @prisma/orm-postgres for PostgreSQL, @prisma/orm-sqlite for SQLite, and @prisma/orm-mongo for MongoDB. The examples here use PostgreSQL.

To start a new project, run npm create prisma@latest -- my-app. To add Prisma ORM 8 to a project that has no Prisma ORM at all, run npx prisma orm init. If you already have a Prisma ORM 7 schema.prisma, follow the PostgreSQL upgrade guide instead, and Coming from Prisma ORM 7 lists what changed. Both npm create prisma@latest and npx prisma orm init write prisma.config.ts, the contract file, and src/prisma/db.ts, and install the database package.

The contract file is either a PSL file (contract.prisma) or a TypeScript file (contract.ts). The file extension selects the authoring mode, so to author in TypeScript you point contract at ./src/prisma/contract.ts. Both modes describe the same things: models with fields and relations, the tables and columns they map to, named types, enums, and any types that extension packages add. Extension packages are npm packages that add field types and database features, such as pgvector, a PostgreSQL extension for vector columns.

After every change to the contract, run these three commands:

bunx prisma contract emit
bunx prisma migration plan
bunx prisma db migrate

npx prisma contract emit writes contract.json and contract.d.ts beside the contract file, so src/prisma/. npx prisma migration plan compares your contract against the last one and writes a migration. npx prisma db migrate applies it and records the match for you. When the database already matches the contract, run npx prisma db sign, which records the match without applying anything, for example after npx prisma contract infer, which writes a contract from an existing database.

db is the client you create once in src/prisma/db.ts, and npx prisma orm init writes that file for you. From a file directly inside src/, import it with import { db } from "./prisma/db" and query a model: await db.orm.public.User.all() returns every user row. From a deeper file, adjust the relative path. db.orm is the ORM client, one of the three query APIs, and public is the PostgreSQL schema, the namespace your tables are in, unless you configured a different one. Reading data covers queries.

Two authoring modes, one contract.json

PSL is the usual way to write the contract. It is a compact language for describing data. It is what npm create prisma@latest scaffolds, and what npx prisma contract infer writes when you start from an existing database.

Define models with the TypeScript builder instead when you want to build them with code. Reach for it when model definitions must be composed, generated, or shared as ordinary TypeScript modules. That page shows what a contract.ts file looks like.

Both modes produce the same contract, so migrations, database checks, and db behave the same no matter which mode you write. A project has exactly one contract file. Do not keep both a contract.prisma and a contract.ts: the config names one file and Prisma ORM reads only that one, so edits to the other file do nothing. To switch modes, change the path in contract and delete the old file.

What the contract contains

The contract describes structure, not data:

  • models, fields, and relations, plus how they map to tables and columns
  • how the data is stored: primary keys, unique constraints, indexes, and foreign keys
  • named types, which are reusable aliases for a database column type, and enums
  • type blocks, also called value objects, each a reusable group of fields such as an address, stored inside its parent row with no table of its own
  • the types and database features that extension packages add, such as pgvector's Vector type

It contains no rows, no credentials, and no connection details, so committing the source, contract.json, and contract.d.ts to version control is safe and expected.

Prompt your coding agent

Projects created with npm create prisma@latest include the Prisma ORM skills for your coding agent. In an existing project, run npx prisma skills sync. The prisma-8 skill covers the contract. Ask your agent to:

  • "Using the prisma-8 skill, explain what our contract.json currently declares."
  • "Add an Invoice model to the contract and run prisma contract emit."
  • "Check whether our database still satisfies the contract."

Next steps

  • Model your data before writing the contract: models, keys, and relations.

On this page