DEV Community

Xavier Carrera Gimbert
Xavier Carrera Gimbert

Posted on • Edited on

Setting Up NestJS with Prisma (Without the Headache)

Starting a project with NestJS and Prisma should be easy, right? They’re both popular technologies and a great match. There are even official articles (1)(2) explaining how to integrate them.

Wrong.

For some reason, those articles are outdated. So here I am, writing this guide to save you a serious headache when setting up your project.

Let's Get to It

💡 Here is the final code of this set up project. Use it if you get stuck.

💡 I’ll be using pnpm for this project, but feel free to use any package manager you prefer.

1. Create the Project

You’ll be prompted to choose a package manager. Select pnpm if you want to follow this guide without changes. Otherwise, adapt as needed.

💡 At the time of writing, the latest version of @nestjs/cli appears to have a bug, so I'm using an older version. This may have been resolved by the time you're reading.

pnpm dlx @nestjs/cli@11.0.0 new nestjs-prisma-test 
Enter fullscreen mode Exit fullscreen mode

2. Set Up PostgreSQL with Docker

Create a Docker file:

touch docker-compose.yml 
Enter fullscreen mode Exit fullscreen mode

Add the following content:

# docker-compose.yml version: '3.8' services: postgres: image: postgres:13.5 restart: always environment: - POSTGRES_USER=myuser - POSTGRES_PASSWORD=mypassword volumes: - postgres:/var/lib/postgresql/data ports: - '5432:5432' volumes: postgres: 
Enter fullscreen mode Exit fullscreen mode

Run the container and keep the terminal open:

docker-compose up 
Enter fullscreen mode Exit fullscreen mode

3. Install Prisma

pnpm add prisma -D 
Enter fullscreen mode Exit fullscreen mode

Initialize Prisma:

pnpm dlx prisma init 
Enter fullscreen mode Exit fullscreen mode

4. Configure Environment Variables

Install dotenv:

pnpm add dotenv 
Enter fullscreen mode Exit fullscreen mode

Update your config files to load environment variables:

// prisma.config.ts import 'dotenv/config'; // rest of the file... 
Enter fullscreen mode Exit fullscreen mode
// src/main.ts import 'dotenv/config'; // rest of the file... 
Enter fullscreen mode Exit fullscreen mode

Update your .env file (remove any comments):

DATABASE_URL="postgres://myuser:mypassword@localhost:5432" 
Enter fullscreen mode Exit fullscreen mode

5. Define Your Models

Edit prisma/schema.prisma:

model User { id Int @id @default(autoincrement()) email String @unique name String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } 
Enter fullscreen mode Exit fullscreen mode

Run the initial migration:

pnpm dlx prisma migrate dev --name "init" 
Enter fullscreen mode Exit fullscreen mode

6. Install Prisma Client

pnpm add @prisma/client 
Enter fullscreen mode Exit fullscreen mode

💡 You don’t need to run generate now - Prisma does it automatically when installing the client. But for future schema changes, run:

pnpm dlx prisma generate 

7. Create the Prisma Service

Note: We import from /client, not as shown in the official docs.

// src/services/prisma.service.ts import { Injectable, OnModuleInit } from '@nestjs/common'; import { PrismaClient } from 'generated/prisma/client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit { async onModuleInit() { await this.$connect(); } } 
Enter fullscreen mode Exit fullscreen mode

8. Register the Prisma Service

// src/app.module.ts import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { PrismaService } from './services/prisma.service'; @Module({ imports: [], controllers: [AppController], providers: [PrismaService], }) export class AppModule {} 
Enter fullscreen mode Exit fullscreen mode

9. Use the Prisma Service

// src/app.controller.ts import { Controller, Get } from '@nestjs/common'; import { PrismaService } from './services/prisma.service'; @Controller() export class AppController { constructor(private readonly prismaService: PrismaService) {} @Get() async getUsers() { return this.prismaService.user.findMany(); } } 
Enter fullscreen mode Exit fullscreen mode

💡 This is a minimal setup and not production-ready. In a real app, you shouldn’t call a service directly from the controller. But this is a Prisma + NestJS set up tutorial - so I don’t care.

10. Run the Server

pnpm run start:dev 
Enter fullscreen mode Exit fullscreen mode

And that’s it! Populate your database and test the endpoint.

If you run into any issues, let me know in the comments. Hope you enjoyed the ride!

Top comments (6)

Collapse
 
cristea_theodora_6200140b profile image
Theodora Cristea • Edited

Very useful post! 👏🏻

Collapse
 
denniske profile image
Dennis

Hi, this tutorial helped me a lot. Thank you!

Can you provide an update for Prisma 7 which was released a few days ago?
https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-7?utm_source=blog&utm_campaign=prisma7

Collapse
 
xavier_carreragimbert profile image
Xavier Carrera Gimbert

I’m really glad it helped, Dennis! It should work fine without any major changes. Did you run into any issues while using Prisma 7?

Collapse
 
denniske profile image
Dennis

I tried to fix it, but it was too complicated for me. I decided to wait for the official sample to be updated: github.com/nestjs/nest/issues/15965

Maybe you can join there.

Collapse
 
pooria1998 profile image
Pouria Kheiri

Great post!
but why is dotenv necessary in "main.ts"? I'm a beginner and I'm a little confused. is it required for specifically using prisma or does it completely replace nest/config?

Collapse
 
xavier_carreragimbert profile image
Xavier Carrera Gimbert

Dotenv is necessary because it allows NestJS to access the database URL stored in the .env file.

It doesn’t replace the NestJS config. It’s simply an add-on.

Hopefully, this explanation helps!

Feel free to ask if you have any other question.