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
💡 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
2. Set Up PostgreSQL with Docker
Create a Docker file:
touch docker-compose.yml
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:
Run the container and keep the terminal open:
docker-compose up
3. Install Prisma
pnpm add prisma -D
Initialize Prisma:
pnpm dlx prisma init
4. Configure Environment Variables
Install dotenv:
pnpm add dotenv
Update your config files to load environment variables:
// prisma.config.ts
import 'dotenv/config';
// rest of the file...
// src/main.ts
import 'dotenv/config';
// rest of the file...
Update your .env file (remove any comments):
DATABASE_URL="postgres://myuser:mypassword@localhost:5432"
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
}
Run the initial migration:
pnpm dlx prisma migrate dev --name "init"
6. Install Prisma Client
pnpm add @prisma/client
💡 You don’t need to run
generatenow – 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();
}
}
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 {}
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();
}
}
💡 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
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!
