Skip to main content
Prisma Documentation Docs

Search documentation

Type to search this documentation.

On this pageOverview

NestJS

This guide shows you how to use Prisma ORM with NestJS, a Node.js framework for building server-side applications with TypeScript. You'll build a REST API with NestJS that uses Prisma ORM to store and retrieve data from a database.

Prisma ORM is an open-source ORM for Node.js and TypeScript. It is used as an alternative to writing plain SQL, or using another database access tool such as SQL query builders (like knex.js) or ORMs (like TypeORM and Sequelize). Prisma currently supports PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and CockroachDB.

While Prisma can be used with plain JavaScript, it is designed for TypeScript and generates types for your models and for the results of each query.

You can find a ready-to-run example in the NestJS example on GitHub

Run one command to scaffold a NestJS project with Prisma ORM and Prisma Postgres ready to go:

title="bun"
bunx create-prisma@stable --template nest
pnpm
pnpm create prisma@stable --template nest
yarn
yarn create prisma@stable --template nest
npm
npm create prisma@stable -- --template nest

Or follow the steps below to set it up manually.

Install the NestJS CLI and create a new project:

bun add --global @nestjs/cli
Bash
pnpm add -g @nestjs/cli
Bash
yarn global add @nestjs/cli
Bash
npm install -g @nestjs/cli
Bash
nest new nestjs-prisma

When prompted, select npm as your package manager. Navigate to the project directory:

Bash
cd nestjs-prisma

You can run npm start to start your application at http://localhost:3000/. Over the course of this guide, you'll add routes to store and retrieve data about users and posts.

In package.json, add the type field set to "module":

package.json
{  "type": "module"}
nest new nestjs-prisma

When prompted, select npm as your package manager. Navigate to the project directory:

cd nestjs-prisma

You can run npm start to start your application at http://localhost:3000/. Over the course of this guide, you'll add routes to store and retrieve data about users and posts.

In package.json, add the type field set to "module":

title="package.json"
{

  "type": "module"

}

Install the necessary Prisma packages and database drivers:

title="bun"
bun add prisma@prev --dev
pnpm
pnpm add prisma@prev --save-dev
yarn
yarn add prisma@prev --dev
npm
npm install prisma@prev --save-dev
bun add @prisma/client@7 @prisma/adapter-pg pg
Bash
pnpm add @prisma/client@7 @prisma/adapter-pg pg
Bash
yarn add @prisma/client@7 @prisma/adapter-pg pg
Bash
npm install @prisma/client@7 @prisma/adapter-pg pg

[!NOTE] If you are using a different database provider (MySQL, SQL Server), install the corresponding driver adapter package instead of @prisma/adapter-pg. For more information, see Database drivers.

Initialize Prisma in your project:

title="bun"
bunx --bun prisma init --output ../src/generated/prisma
pnpm
pnpm prisma init --output ../src/generated/prisma
yarn
yarn prisma init --output ../src/generated/prisma
npm
npx prisma init --output ../src/generated/prisma

This creates a new prisma directory with the following contents:

  • schema.prisma: Specifies your database connection and contains the database schema
  • prisma.config.ts: A configuration file for your projects
  • .env: A dotenv file, typically used to store your database credentials in a group of environment variables

Create a Prisma Postgres database and replace the generated DATABASE_URL in your .env file with the postgres://... connection string from the CLI output:

title="bun"
bunx create-db
pnpm
pnpm dlx create-db
yarn
yarn dlx create-db
npm
npx create-db

Specify your output path for the generated Prisma client by either passing --output ../src/generated/prisma during prisma init or directly in your Prisma schema:

title="prisma/schema.prisma"
generator client {

  provider = "prisma-client"

  output   = "../src/generated/prisma"

}

Your database connection is configured in the datasource block in your schema.prisma file. By default it's set to postgresql which is what you need for this guide.

title="prisma/schema.prisma"
generator client {

  provider = "prisma-client"

  output   = "../src/generated/prisma"

}

datasource db {

  provider = "postgresql"

}

Now, open up .env and you should see a DATABASE_URL already specified:

title=".env"
DATABASE_URL="postgres://..."

Add the following two models to your schema.prisma file:

title="prisma/schema.prisma"
model User {

  id    Int     @id @default(autoincrement())

  email String  @unique

  name  String?

  posts Post[]

}

model Post {

  id        Int      @id @default(autoincrement())

  title     String

  content   String?

  published Boolean? @default(false)

  author    User?    @relation(fields: [authorId], references: [id])

  authorId  Int?

}

With your Prisma models in place, you can generate your SQL migration files and run them against the database. Run the following commands in your terminal:

bunx prisma migrate dev --name init
Bash
pnpm prisma migrate dev --name init
Bash
yarn prisma migrate dev --name init
Bash
npx prisma migrate dev --name init

This prisma migrate dev command generates SQL files and directly runs them against the database. In this case, the following migration files was created in the existing prisma directory:

Bash
$ tree prisma
prisma
├── migrations
│   └── 20201207100915_init
│       └── migration.sql
└── schema.prisma

This prisma migrate dev command generates SQL files and directly runs them against the database. In this case, the following migration files was created in the existing prisma directory:

$ tree prisma

prisma

├── migrations

│   └── 20201207100915_init

│       └── migration.sql

└── schema.prisma

Once installed, you can run the generate command to generate the types and Client needed for your project. If any changes are made to your schema, you will need to rerun the generate command to keep those types in sync.

title="bun"
bunx prisma generate
pnpm
pnpm prisma generate
yarn
yarn prisma generate
npm
npx prisma generate

You're now able to send database queries with Prisma Client. When setting up your NestJS application, you'll want to abstract away the Prisma Client API for database queries within a service. To get started, you can create a new PrismaService that takes care of instantiating PrismaClient and connecting to your database.

Inside the src directory, create a new file called prisma.service.ts and add the following code to it:

title="src/prisma.service.ts"
import { Injectable } from "@nestjs/common";

import { PrismaClient } from "./generated/prisma/client.js";

import { PrismaPg } from "@prisma/adapter-pg";

@Injectable()

export class PrismaService extends PrismaClient {

  constructor() {

    const adapter = new PrismaPg({

      connectionString: process.env.DATABASE_URL as string,

    });

    super({ adapter });

  }

}

Next, you can write services that you can use to make database calls for the User and Post models from your Prisma schema.

Still inside the src directory, create a new file called user.service.ts and add the following code to it:

title="src/user.service.ts"
import { Injectable } from "@nestjs/common";

import { PrismaService } from "./prisma.service.js";

import { User, Prisma } from "./generated/prisma/client.js";

@Injectable()

export class UserService {

  constructor(private prisma: PrismaService) {}

  async user(userWhereUniqueInput: Prisma.UserWhereUniqueInput): Promise<User | null> {

    return this.prisma.user.findUnique({

      where: userWhereUniqueInput,

    });

  }

  async users(params: {

    skip?: number;

    take?: number;

    cursor?: Prisma.UserWhereUniqueInput;

    where?: Prisma.UserWhereInput;

    orderBy?: Prisma.UserOrderByWithRelationInput;

  }): Promise<User[]> {

    const { skip, take, cursor, where, orderBy } = params;

    return this.prisma.user.findMany({

      skip,

      take,

      cursor,

      where,

      orderBy,

    });

  }

  async createUser(data: Prisma.UserCreateInput): Promise<User> {

    return this.prisma.user.create({

      data,

    });

  }

  async updateUser(params: {

    where: Prisma.UserWhereUniqueInput;

    data: Prisma.UserUpdateInput;

  }): Promise<User> {

    const { where, data } = params;

    return this.prisma.user.update({

      data,

      where,

    });

  }

  async deleteUser(where: Prisma.UserWhereUniqueInput): Promise<User> {

    return this.prisma.user.delete({

      where,

    });

  }

}

Notice how you're using Prisma Client's generated types to ensure that the methods that are exposed by your service are properly typed. You therefore save the boilerplate of typing your models and creating additional interface or DTO files.

Now do the same for the Post model.

Still inside the src directory, create a new file called post.service.ts and add the following code to it:

title="src/post.service.ts"
import { Injectable } from "@nestjs/common";

import { PrismaService } from "./prisma.service.js";

import { Post, Prisma } from "./generated/prisma/client.js";

@Injectable()

export class PostService {

  constructor(private prisma: PrismaService) {}

  async post(postWhereUniqueInput: Prisma.PostWhereUniqueInput): Promise<Post | null> {

    return this.prisma.post.findUnique({

      where: postWhereUniqueInput,

    });

  }

  async posts(params: {

    skip?: number;

    take?: number;

    cursor?: Prisma.PostWhereUniqueInput;

    where?: Prisma.PostWhereInput;

    orderBy?: Prisma.PostOrderByWithRelationInput;

  }): Promise<Post[]> {

    const { skip, take, cursor, where, orderBy } = params;

    return this.prisma.post.findMany({

      skip,

      take,

      cursor,

      where,

      orderBy,

    });

  }

  async createPost(data: Prisma.PostCreateInput): Promise<Post> {

    return this.prisma.post.create({

      data,

    });

  }

  async updatePost(params: {

    where: Prisma.PostWhereUniqueInput;

    data: Prisma.PostUpdateInput;

  }): Promise<Post> {

    const { data, where } = params;

    return this.prisma.post.update({

      data,

      where,

    });

  }

  async deletePost(where: Prisma.PostWhereUniqueInput): Promise<Post> {

    return this.prisma.post.delete({

      where,

    });

  }

}

Your UserService and PostService currently wrap the CRUD queries that are available in Prisma Client. In a real world application, the service would also be the place to add business logic to your application. For example, you could have a method called updatePassword inside the UserService that would be responsible for updating the password of a user.

Finally, you'll use the services you created in the previous sections to implement the different routes of your app. For the purpose of this guide, you'll put all your routes into the already existing AppController class.

Replace the contents of the app.controller.ts file with the following code:

title="src/app.controller.ts"
import { Controller, Get, Param, Post, Body, Put, Delete } from "@nestjs/common";

import { UserService } from "./user.service.js";

import { PostService } from "./post.service.js";

import { User as UserModel } from "./generated/prisma/client.js";

import { Post as PostModel } from "./generated/prisma/client.js";

@Controller()

export class AppController {

  constructor(

    private readonly UserService: UserService,

    private readonly postService: PostService,

  ) {}

  @Get("post/:id")

  async getPostById(@Param("id") id: string): Promise<PostModel | null> {

    return this.postService.post({ id: Number(id) });

  }

  @Get("feed")

  async getPublishedPosts(): Promise<PostModel[]> {

    return this.postService.posts({

      where: { published: true },

    });

  }

  @Get("filtered-posts/:searchString")

  async getFilteredPosts(@Param("searchString") searchString: string): Promise<PostModel[]> {

    return this.postService.posts({

      where: {

        OR: [

          {

            title: { contains: searchString },

          },

          {

            content: { contains: searchString },

          },

        ],

      },

    });

  }

  @Post("post")

  async createDraft(

    @Body() postData: { title: string; content?: string; authorEmail: string },

  ): Promise<PostModel> {

    const { title, content, authorEmail } = postData;

    return this.postService.createPost({

      title,

      content,

      author: {

        connect: { email: authorEmail },

      },

    });

  }

  @Post("user")

  async signupUser(@Body() userData: { name?: string; email: string }): Promise<UserModel> {

    return this.UserService.createUser(userData);

  }

  @Put("publish/:id")

  async publishPost(@Param("id") id: string): Promise<PostModel> {

    return this.postService.updatePost({

      where: { id: Number(id) },

      data: { published: true },

    });

  }

  @Delete("post/:id")

  async deletePost(@Param("id") id: string): Promise<PostModel> {

    return this.postService.deletePost({ id: Number(id) });

  }

}

This controller implements the following routes:

  • /post/:id: Fetch a single post by its id
  • /feed: Fetch all published posts
  • /filtered-posts/:searchString: Filter posts by title or content
  • /post: Create a new post

    • Body:

      • title: String (required): The title of the post
      • content: String (optional): The content of the post
      • authorEmail: String (required): The email of the user that creates the post
  • /user: Create a new user

    • Body:

      • email: String (required): The email address of the user
      • name: String (optional): The name of the user
  • /publish/:id: Publish a post by its id
  • /post/:id: Delete a post by its id

Remember to register the new services in the app module.

Update src/app.module.ts to register all services:

title="src/app.module.ts"
import { Module } from "@nestjs/common";

import { AppController } from "./app.controller";

import { ConfigModule } from "@nestjs/config";

import { AppService } from "./app.service.js";

import { PrismaService } from "./prisma.service.js"; 

import { UserService } from "./user.service.js"; 

import { PostService } from "./post.service.js"; 

@Module({

  imports: [ConfigModule.forRoot()],

  controllers: [AppController],

  providers: [AppService, PrismaService, UserService, PostService], 

})

export class AppModule {}

Start your application:

bun start
Bash
pnpm start
Bash
yarn start
Bash
npm start

Test your endpoints with curl, Postman, or HTTPie.

Create a user:

Bash
curl -X POST http://localhost:3000/user \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@prisma.io"}'

Create a post:

Bash
curl -X POST http://localhost:3000/post \
  -H "Content-Type: application/json" \
  -d '{"title": "Hello World", "authorEmail": "alice@prisma.io"}'

Get published posts:

Bash
curl http://localhost:3000/feed

Publish a post:

Bash
curl -X PUT http://localhost:3000/publish/1

Search posts:

Bash
curl http://localhost:3000/filtered-posts/hello

Test your endpoints with curl, Postman, or HTTPie.

Create a user:

curl -X POST http://localhost:3000/user \

  -H "Content-Type: application/json" \

  -d '{"name": "Alice", "email": "alice@prisma.io"}'

Create a post:

curl -X POST http://localhost:3000/post \

  -H "Content-Type: application/json" \

  -d '{"title": "Hello World", "authorEmail": "alice@prisma.io"}'

Get published posts:

curl http://localhost:3000/feed

Publish a post:

curl -X PUT http://localhost:3000/publish/1

Search posts:

curl http://localhost:3000/filtered-posts/hello

In this guide, you learned how to use Prisma ORM with NestJS to implement a REST API. The controller that implements the routes of the API is calling a PrismaService which in turn uses Prisma Client to send queries to a database to fulfill the data needs of incoming requests.

If you want to learn more about using NestJS with Prisma, be sure to check out the following resources:

Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu