Getting Started with Prisma - AI Style

Prisma offers a modern, type-safe ORM experience tailored for TypeScript developers working with relational databases. In this guide, you'll integrate Prisma into an existing Node.js TypeScript project, focusing on setup, schema modelling, and generating database clients. If you're comfortable with databases and want a clean, intuitive API for querying data, Prisma will fit right into your workflow.


The Database

First, we need a database. Let's start with docker compose.

services:
  db:
    image: postgres:16
    restart: always
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: db
    ports:
      - 5432:5432
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Now start it with:

docker compose up -d

Add Prisma to an Existing Project

Since you already have a typescript application up and running, let's add Prisma. I use yarn so I'll use that, but you can use npm, pnpm or any other package manager you like.

yarn add -D prisma

Now, make sure it works.

npx prisma

Set up to use Postgres

Let's initialize Prisma to use PostgreSQL

npx prisma init --datasource-provider postgresql

This will add the necessary packages and create a .env file that has the DATABASE_URL. We'll have to update that to match our docker compose postgres database.

DATABASE_URL="postgres://user:password@localhost:5432/userservice?schema=public"

.env

Create some helper methods for package.json

npm pkg set "scripts.prisma:generate"="prisma generate"
npm pkg set "scripts.prisma:migrate:dev"="prisma migrate dev"
npm pkg set "scripts.prisma:migrate:deploy"="prisma migrate deploy"

Add a post-install handler to generate Prisma files, so that after you run yarn, it will also create the files needed to compile and run the app

npm pkg set "scripts.postinstall"="prisma generate"

Run yarn to make sure the generate command runs

yarn install v1.22.22
[1/4] 🔍  Resolving packages...
success Already up-to-date.
$ prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma

âś” Generated Prisma Client (v6.9.0) to ./src/generated/prisma in 58ms

Start by importing your Prisma Client (See: https://pris.ly/d/importing-client)

Tip: Want to turn off tips and other hints? https://pris.ly/tip-4-nohints


âś” Installed the @prisma/client and prisma packages in your project

âś” Generated Prisma Client (v6.9.0) to ./src/generated/prisma in 99ms

Start by importing your Prisma Client (See: https://pris.ly/d/importing-client)

Tip: Want to turn off tips and other hints? https://pris.ly/tip-4-nohints

✨  Done in 5.28s.

Join the Newsletter

Subscribe to get more DevOps Tips & Tricks

    We won't send you spam. Unsubscribe at any time.

    Create a schema from ChatGPT

    Now we are ready to go. Let's create a schema using ChatGPT

    I'm using prisma with a node application.  
    
    Create for me a prisma schema for a postgres database use uuid's that 
    are generated by default that has the following entities.
    
    User - name, email
    Organization - name
    
    Create a many to many relationship between user and organization and 
    include a role for this link.  Roles can be owner (default), admin or user.

    prompt

    This will create the following schema.prisma that you can add to your project.

    // schema.prisma
    
    generator client {
      provider = "prisma-client-js"
    }
    
    datasource db {
      provider = "postgresql"
      url      = env("DATABASE_URL")
    }
    
    model User {
      id              String              @id @default(uuid()) @db.Uuid
      name            String
      email           String              @unique
      userOrganizations UserOrganization[]
      createdAt       DateTime            @default(now())
      updatedAt       DateTime            @updatedAt
    }
    
    model Organization {
      id              String              @id @default(uuid()) @db.Uuid
      name            String
      userOrganizations UserOrganization[]
      createdAt       DateTime            @default(now())
      updatedAt       DateTime            @updatedAt
    }
    
    model UserOrganization {
      userId         String               @db.Uuid
      organizationId String               @db.Uuid
      role           Role                 @default(OWNER)
    
      user           User                 @relation(fields: [userId], references: [id], onDelete: Cascade)
      organization   Organization         @relation(fields: [organizationId], references: [id], onDelete: Cascade)
    
      @@id([userId, organizationId])
    }
    
    enum Role {
      OWNER
      ADMIN
      USER
    }

    Run yarn prisma:migrate:dev to set this up in the database

    yarn run v1.22.22
    $ prisma migrate dev
    Environment variables loaded from .env
    Prisma schema loaded from prisma/schema.prisma
    Datasource "db": PostgreSQL database "userservice", schema "public" at "localhost:5432"
    
    ✔ Enter a name for the new migration: … init
    Applying migration `20250610023909_init`
    
    The following migration(s) have been created and applied from new schema changes:
    
    migrations/
      └─ 20250610023909_init/
        └─ migration.sql
    
    Your database is now in sync with your schema.
    
    âś” Generated Prisma Client (v6.9.0) to ./src/generated/prisma in 141ms
    
    
    ✨  Done in 9.06s.

    Since this is the first migration, I've called it 'init'.

    I can now connect to it using docker compose exec db psql -U user userservice and see the tables

    psql (16.9 (Debian 16.9-1.pgdg120+1))
    Type "help" for help.
    
    userservice=# \dt
                  List of relations
     Schema |        Name        | Type  | Owner
    --------+--------------------+-------+-------
     public | Organization       | table | user
     public | User               | table | user
     public | UserOrganization   | table | user
     public | _prisma_migrations | table | user
    (4 rows)
    
    userservice=# \d "User"
                                      Table "public.User"
      Column   |              Type              | Collation | Nullable |      Default
    -----------+--------------------------------+-----------+----------+-------------------
     id        | uuid                           |           | not null |
     name      | text                           |           | not null |
     email     | text                           |           | not null |
     createdAt | timestamp(3) without time zone |           | not null | CURRENT_TIMESTAMP
     updatedAt | timestamp(3) without time zone |           | not null |
    Indexes:
        "User_pkey" PRIMARY KEY, btree (id)
        "User_email_key" UNIQUE, btree (email)
    Referenced by:
        TABLE ""UserOrganization"" CONSTRAINT "UserOrganization_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"(id) ON UPDATE CASCADE ON DELETE CASCADE
    
    userservice=#

    With Prisma set up in your TypeScript project, you now have a powerful, type-safe way to work with your database, without sacrificing clarity or developer experience. From schema modelling to querying, Prisma streamlines everyday tasks and helps you catch issues early through tight TypeScript integration. As your application grows, Prisma’s tooling and ecosystem will support you every step of the way.