Back to all posts

What is Prisma ORM? A beginner’s guide

Learn what an ORM is, how Prisma works, how to set it up, and when Prisma is a good fit for a JavaScript or TypeScript application.

••8 min read•1,760 words
What is Prisma ORM? A beginner’s guide

Updated September 29, 2026: I replaced the old install command and schema-only configuration with a tested Prisma 7 SQLite walkthrough, including a migration and a repeatable query. The concepts remain below; only the superseded January 2022 installation steps are under a historical toggle.

If you’ve previously written database queries for Relational Databases you probably understand that it’s not a cakewalk for someone from an OOPs background. This is where ORM or Object Relational Mapping jumps in, allowing us to query and manipulate data from a database through an object-oriented programming language of our choice. Traditionally, if I were to interact with my database, I’d have to write SQL queries. Using an ORM I can simply communicate with the same using code written in JavaScript, for example. In a nutshell, an ORM is nothing but a layer between your code and your database, facilitating communication using methods declared within the framework.

What are the benefits of using an ORM?

The biggest advantage that you get out of implementing an ORM is that you get to write your queries comfortably in the language of your choice. This minimizes the constraints you have in terms of development tremendously. For someone like me who absolutely detests query languages, ORM adds a lot of flexibility in terms of the usage of database(s) as well. Moreover, you can easily reuse your code with minor to no changes.

What is Prisma ORM?

Prisma is a server-side toolkit for reading and writing database records through a generated client. You can start with a new database or connect an existing one. This walkthrough uses SQLite; check the documentation for your Prisma version before choosing another database provider.

In short, it’s an open-sourced ORM segregated into three services, namely:

  1. Prisma Client: A query builder that gets auto-generated from the Prisma schema with types tailored to your application.

  2. Prisma Migrate: A service that automatically generates SQL database migrations, that are fully customizable. For quick data model prototyping in development,prisma db push lets you make changes to the database without generating migration files.

  3. Prisma Studio: A visual database browser that opens in your browser to graphically view and edit the data.

For more details about Prisma, click here (opens in a new tab).

How does Prisma work?

Every project that uses Prisma starts with a schema, typically called schema.prisma. It describes the database provider, generators, and data models. In Prisma 7, a separate configuration file supplies the CLI’s database connection URL, while a driver adapter connects Prisma Client at runtime.

Find the documentation here (opens in a new tab).

Start with Prisma today

I’m using a local SQLite file here so you can try Prisma without provisioning a database server. You still need to understand constraints, migrations, and the queries your app runs.

Tested September 29, 2026: Node.js 22.23.3, npm 11.0.0, Prisma CLI, Client, and @prisma/adapter-better-sqlite3 7.10.0, TypeScript 5.9.3, and tsx 4.20.6 on macOS. Installation, initialization, validation, migration, client generation, type-checking, and two runs of the query below passed against a new local database. This is a Prisma 7 tutorial: the npm latest tag pointed to a Prisma 8 release candidate during this update, so the commands deliberately pin 7.10.0.

Set up a local project

Use Node.js 22.23.3 and npm 11.0.0 to reproduce this baseline. The commands use a macOS/Linux shell. Run them in a new folder, not inside an existing database project:

Bash
mkdir hello-prismacd hello-prismanpm init -ynpm pkg set type=modulenpm install --save-dev --save-exact prisma@7.10.0 typescript@5.9.3 tsx@4.20.6 @types/node@22.19.15 @types/better-sqlite3@7.6.13npm install --save-exact @prisma/client@7.10.0 @prisma/adapter-better-sqlite3@7.10.0 dotenv@17.2.3npx prisma init --datasource-provider sqlite --output ../generated/prisma

--save-dev is the npm flag; the typographic dash in the old article’s —-dev command was wrong. Keep package-lock.json and use npm ci to reproduce later installs.

The test install’s npm audit reported advisories in the Prisma CLI’s transitive deepmerge-ts and mysql2 dependencies. This local SQLite exercise passed, but that is not a clean dependency security audit. Review those advisories and available fixes before adopting this toolchain for a deployed application; do not blindly run npm audit fix --force across major versions.

Create tsconfig.json at the project root:

tsconfig.json
{  "compilerOptions": {    "target": "ES2023",    "module": "ESNext",    "moduleResolution": "bundler",    "strict": true,    "esModuleInterop": true,    "skipLibCheck": true,    "noEmit": true  }}

Define the schema and connection

Replace prisma/schema.prisma with one small model:

prisma/schema.prisma
generator client {  provider = "prisma-client"  output   = "../generated/prisma"}datasource db {  provider = "sqlite"}model User {  id    Int    @id @default(autoincrement())  email String @unique  name  String}

Prisma 7 keeps the CLI connection URL in a config file, rather than the schema’s datasource block. Starting with 7.10, prisma init names it prisma7.config.ts; existing Prisma 7 projects can still use prisma.config.ts. This example follows the version 7 SQLite quickstart (opens in a new tab).

Use this generated configuration:

prisma7.config.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') },});

Set .env in the project root:

.env
DATABASE_URL="file:./dev.db"

Run every command below from the project root so the CLI and the SQLite adapter resolve the same database file. Keep .env, dev.db, and any dev.db-* sidecar files out of Git; retain the generated ignore rules for dependencies and the generated client too. Commit the schema, config, migration directory, source, and lockfile.

Migrate and generate the client

Bash
npx prisma validatetouch dev.dbnpx prisma migrate dev --name initnpx prisma generate

On this tested Prisma 7.10.0/macOS setup, migrating before dev.db existed failed with “Schema engine error.” touch dev.db creates an empty SQLite file without truncating an existing file, and the migration then succeeds. Run it from the project root, where the configured URL points.

For this fresh project, the migration creates a User table and a migration history. Run generate explicitly after schema changes; this Prisma 7 workflow does not rely on migration to generate a client. Prisma’s migration documentation (opens in a new tab) distinguishes migrate dev for development from migrate deploy for applying committed migrations in production.

Do not run this initial migration against a populated production database. For an existing database, start with introspection (opens in a new tab) and migration baselining (opens in a new tab) instead. db pull reads a database into a schema; db push changes a database without creating migration history. They are not interchangeable with the migration above.

Write and read a record

Create script.ts at the project root:

script.ts
import 'dotenv/config';import assert from 'node:assert/strict';import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3';import { PrismaClient } from './generated/prisma/client'; const url = process.env.DATABASE_URL;if (!url) throw new Error('Set DATABASE_URL in .env'); const prisma = new PrismaClient({ adapter: new PrismaBetterSqlite3({ url }) }); try {  await prisma.user.upsert({    where: { email: 'reader@example.com' },    update: { name: 'Reader' },    create: { email: 'reader@example.com', name: 'Reader' },  });  const user = await prisma.user.findUniqueOrThrow({    where: { email: 'reader@example.com' },  });  assert.equal(user.name, 'Reader');  assert.equal(await prisma.user.count(), 1);  console.log(`${user.name}: ${user.email}`);} finally {  await prisma.$disconnect();}
Bash
npx tsc --noEmitnpx tsx script.tsnpx tsx script.ts

Both runs should print Reader: reader@example.com. The unique email and upsert keep this example repeatable; the assertions check the read and ensure that rerunning it did not add a duplicate to the fresh database. A failing query or assertion exits unsuccessfully, while finally closes the connection.

This is a one-off script. In a long-running server, reuse one Prisma Client (opens in a new tab) rather than connecting and disconnecting for every request. Prisma belongs in server-side code, never a browser bundle. PostgreSQL and other databases need their own driver adapter and connection configuration; this SQLite setup is not a drop-in production recipe for every provider.

Why use Prisma?

Prisma’s main goal is to make application developers more productive when working with databases.

It is an upgraded ORM that mitigates many problems of traditional ORMs, such as bloated model instances, mixing business with storage logic, lack of type-safety, or unpredictable queries.

It uses the Prisma schema to define application models in a declarative way. Prisma Migrate then allows to generate SQL migrations from the Prisma schema and executes them against the database. CRUD queries are provided by Prisma Client, a lightweight and entirely type-safe database client for Node.js and TypeScript.

Ending Notes

ORM is advantageous for the folks who have a stronger background in OOPs and not SQL or query languages. Only consider implementing this system if you’re ready to learn more about the ORM library, what it offers and how to set it up error-free, otherwise, you might end up wasting your time instead of trying to save it. Even if you dive into ORM, continue to practice and have a good hold over SQL and other query languages.

Of all the different kinds of ORMs out there, I felt that Prisma was way ahead of all the competitors, thanks to the vast beginner-friendly documentation and this comparison (opens in a new tab) page too.

Historical installation instructions

Read the superseded January 2022 installation steps (historical)

Historical reference — not current setup instructions. These steps predate Prisma 7’s configuration file, generated-client output, and driver-adapter setup. The malformed install flag and old configuration are preserved for context, not for use. Follow the pinned walkthrough above for a new project.

How to install Prisma

  1. In order to get started, we’ll install the Prisma CLI tool as a development dependency using npm install —-dev prisma.

  2. Now we’ll set up our Prisma project by creating the Prisma schema file template with npx prisma init. This creates a /prismafolder with a schema.prisma file at the root of the project. There’s also new /.env that you should add to .gitignore.

  3. To connect your database, you need to set the url field of the datasource block in your Prisma schema to your database connection URL. The format of the connection URL for your database depends on the database you use.

  4. With the npx prisma db pullcommand, Prisma can pull the pre-existing database schema and on its own copy and refactor it into the schema.prisma file. Alternatively, you can also install and generate Prisma Client. Simply run npm install @prisma/client, followed by npx prisma generate. This command reads your Prisma schema and generates your Prisma Client library.