How to Use Prisma with NestJS: Setup and Example
To use
Prisma with NestJS, install Prisma packages, generate the client, then create a PrismaService that extends PrismaClient. Inject this service into your modules to access the database with type-safe queries.Syntax
Here is the basic syntax pattern to integrate Prisma with NestJS:
- Install Prisma: Use
npm install @prisma/clientandnpm install prisma --save-dev. - Generate Prisma Client: Run
npx prisma generateafter defining your schema. - Create PrismaService: Extend
PrismaClientand use@Injectable()to make it injectable. - Use PrismaService: Inject it into your modules and services to perform database operations.
typescript
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { async onModuleInit() { await this.$connect(); } async onModuleDestroy() { await this.$disconnect(); } }
Example
This example shows a simple NestJS module using PrismaService to fetch all users from the database.
typescript
import { Module, Injectable } from '@nestjs/common'; import { User } from '@prisma/client'; import { PrismaService } from './prisma.service'; @Injectable() export class UserService { constructor(private prisma: PrismaService) {} async getAllUsers(): Promise<User[]> { return this.prisma.user.findMany(); } } @Module({ providers: [PrismaService, UserService], exports: [UserService], }) export class UserModule {} // Usage in a controller or another service // const users = await userService.getAllUsers();
Output
[{ id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' }]
Common Pitfalls
Common mistakes when using Prisma with NestJS include:
- Not calling
$connect()and$disconnect()inPrismaService, which can cause connection leaks. - Injecting
PrismaClientdirectly instead of using a service wrapper, leading to poor lifecycle management. - Forgetting to run
npx prisma generateafter schema changes, causing runtime errors.
typescript
/* Wrong way: Using PrismaClient directly without service */ import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function getUsers() { return prisma.user.findMany(); } /* Right way: Use PrismaService with lifecycle hooks */ import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { async onModuleInit() { await this.$connect(); } async onModuleDestroy() { await this.$disconnect(); } }
Quick Reference
| Step | Command/Code | Description |
|---|---|---|
| 1 | npm install @prisma/client prisma --save-dev | Install Prisma packages |
| 2 | npx prisma init | Initialize Prisma schema and config |
| 3 | Define schema.prisma | Set your database models |
| 4 | npx prisma generate | Generate Prisma Client |
| 5 | Create PrismaService | Wrap PrismaClient with NestJS service |
| 6 | Inject PrismaService | Use in modules and services for DB access |
Key Takeaways
Create a PrismaService extending PrismaClient with lifecycle hooks for connection management.
Always run 'npx prisma generate' after schema changes to update the client.
Inject PrismaService into your NestJS modules to access the database safely.
Avoid using PrismaClient directly to prevent connection and lifecycle issues.
Use async/await with Prisma queries inside your NestJS services for clean code.