DEV Community

Cover image for Getting to Know Prisma: A Beginner’s Guide with Examples
Sagar Kumar
Sagar Kumar

Posted on

Getting to Know Prisma: A Beginner’s Guide with Examples

Prisma is an incredible tool for developers working with databases, offering a modern ORM (Object-Relational Mapping) experience. Recently, I dove into Prisma with PostgreSQL for a project and found myself exploring its features hands-on. One task stood out: adding a new model to my Prisma schema and syncing it with my PostgreSQL database. While Prisma’s documentation is thorough, it can feel overwhelming. So, I’m sharing my simplified explanation—along with examples—based on my journey.

In this article, I'll cover how to add a new model, the difference between prisma migrate devand prisma migrate deploy, and why choosing the right command matters depending on your environment.

Let's Add a New Model: The Starting Point

Let’s say I’m building a blog app and already have a User model in my schema.prisma file. Now, I want to add a Post model so users can create blog posts. Here’s what my initial schema.prisma might look like:

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

generator client {
  provider = "prisma-client-js"
}

model User {
  id    Int     @id @default(autoincrement())
  name  String
}
Enter fullscreen mode Exit fullscreen mode

To add the Post model, I update the schema.prisma file like this:

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

generator client {
  provider = "prisma-client-js"
}

model User {
  id    Int     @id @default(autoincrement())
  name  String
  posts Post[]  // Relation to Post model
}

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String
  authorId  Int
  author    User    @relation(fields: [authorId], references: [id])
}
Enter fullscreen mode Exit fullscreen mode

After adding the Post model, I ran:

npx prisma generate
Enter fullscreen mode Exit fullscreen mode

This updates the Prisma Client with the new model, but my PostgreSQL database doesn’t reflect this change yet. To sync the database, I need to use Prisma’s migration commands.
That’s where prisma migrate dev and prisma migrate deploy come in—but which one should I use, and why?

Understanding prisma migrate dev

Since I’m working locally, I opted for prisma migrate dev. Here’s what it does, step by step:

  1. Detects Schema Drifts: It compares my schema.prisma file with the actual database structure. If there’s a mismatch (e.g., a missing table or column), it suggests changes. Be cautious here—applying these suggestions unwisely can lead to data loss. (I’ll cover how to handle this safely in a future article.)

  2. Generates a Migration File: It creates a SQL migration file in the prisma/migrations folder based on the changes. For my Post model, the file might look like this:

CREATE TABLE "Post" (
    "id" SERIAL PRIMARY KEY,
    "title" TEXT NOT NULL,
    "content" TEXT NOT NULL,
    "authorId" INTEGER NOT NULL,
    FOREIGN KEY ("authorId") REFERENCES "User"("id")
);
Enter fullscreen mode Exit fullscreen mode
  1. Applies the Migration: It runs the SQL against my local PostgreSQL database, creating the Post table.

  2. Saves Migration History: It stores a record of the migration (with a SHA256 hash) in a special _prisma_migrations table. This tracks which migrations have been applied.

  3. Updates the Prisma Client: It regenerates the Prisma Client to include the new Post model, so I can query it in my code.

To run this, I used:

npx prisma migrate dev --name add_post_model
Enter fullscreen mode Exit fullscreen mode

The --name flag gives the migration a descriptive name (e.g., add_post_model). After running it, I can now use the Post model in my app:

const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();

async function createPost() {
  const post = await prisma.post.create({
    data: {
      title: 'My First Post',
      content: 'Hello, Prisma!',
      authorId: 1,
    },
  });
  console.log(post);
}

createPost();
Enter fullscreen mode Exit fullscreen mode

This command is perfect for local development because it handles everything—drift detection, migration creation, and client updates—in one go.

Why Use prisma migrate deploy Elsewhere?

Now, imagine I’m ready to push my app to production or a testing environment. Here, prisma migrate dev isn’t the right choice. Instead, I use:

npx prisma migrate deploy
Enter fullscreen mode Exit fullscreen mode

Here’s why: prisma migrate deploy is more limited—and that’s intentional. It only does two things:

  1. Applies Existing Migration Files: It runs the SQL files in the prisma/migrations folder against the database, in the order they were created.

  2. Updates the Migration History: It ensures the _prisma_migrations table reflects the applied migrations.

It skips drift detection, migration file generation, and Prisma Client regeneration (Steps 1, 2, 4, and 5 from migrate dev). This makes it safer and more predictable in production:

  1. No Drift Detection: Production databases shouldn’t be auto-corrected based on schema drift. That could lead to unintended changes or data loss.

  2. No New Migrations: Migration files should be created and tested locally, then committed to version control—not generated on the fly in production.

  3. No Client Regeneration: The Prisma Client is typically built during the app’s deployment process, not during migration.

For example, after running prisma migrate dev locally and committing the migration files, I deploy my app to production. On the production server, I run:

npx prisma migrate deploy
Enter fullscreen mode Exit fullscreen mode

This applies the add_post_model migration to the production PostgreSQL database, ensuring it matches my local setup without extra steps.

Key Takeaways

Use prisma migrate dev in development to create and apply migrations, detect drifts, and update the Prisma Client. It’s a full-featured tool for experimenting locally.

Use prisma migrate deploy in production or testing to apply pre-existing migrations safely, without altering the database beyond what’s planned.
Always test migrations locally first to avoid surprises in production.
Prisma’s migration system is powerful, but the distinction between these commands confused me at first. The official docs are detailed, but I hope this simpler breakdown—complete with examples—helps you get started faster.

Stay tuned for my next article on preventing data loss during migrations!

Some Important Links:

  1. Prisma Migrate Dev
  2. Prisma Migrate Deploy

Top comments (0)