{"id":479173,"date":"2026-05-09T22:18:26","date_gmt":"2026-05-09T22:18:26","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=479173"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=479173","title":{"rendered":"How to connect MySQL in your backend project (NestJS + Prisma)"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>Hi! While working on a backend project, I ran into a simple but annoying problem \u2014 I couldn\u2019t find a clear and <strong>complete guide on connecting MySQL to a basic backend project<\/strong>.<\/p>\n<p>Most tutorials either:<\/p>\n<ul>\n<li>\n<p> skip important steps <\/p>\n<\/li>\n<li>\n<p> assume too much prior knowledge <\/p>\n<\/li>\n<li>\n<p> or don\u2019t explain <em>why things work the way they do<\/em> <\/p>\n<\/li>\n<\/ul>\n<p>So in this guide, I\u2019ll show you:<\/p>\n<ul>\n<li>\n<p> how to connect MySQL using NestJS + Prisma <\/p>\n<\/li>\n<li>\n<p> how it works under the hood <\/p>\n<\/li>\n<li>\n<p> and how to use it in a <strong>monorepo setup<\/strong> <\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h2>\ud83d\udccc Why Prisma?<\/h2>\n<p>Before we start \u2014 a quick note.<\/p>\n<p>Prisma is not just another ORM. It provides:<\/p>\n<ul>\n<li>\n<p><strong>type-safe database queries<\/strong> <\/p>\n<\/li>\n<li>\n<p> auto-generated client based on schema <\/p>\n<\/li>\n<li>\n<p> better developer experience than classic ORMs like TypeORM <\/p>\n<\/li>\n<\/ul>\n<p>In simple terms: less SQL, fewer runtime errors, more productivity.<\/p>\n<h2>Create a NestJS project<\/h2>\n<pre><code class=\"bash\">npm i -g @nestjs\/clinest new my-backend-projectcd my-backend-projectnpm install<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Run it:<\/p>\n<pre><code class=\"bash\">npm run start<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>Install Prisma<\/h2>\n<pre><code class=\"bash\">npm install prisma --save-devnpm install @prisma\/client<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Initialize Prisma:<\/p>\n<pre><code class=\"bash\">npx prisma init<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\ud83d\udca1 Best practice: always use <code>npx prisma<\/code> instead of global CLI <\/p>\n<hr\/>\n<h2>\ud83d\udcc1 After initialization, you\u2019ll get:<\/h2>\n<ul>\n<li>\n<p><code>schema.prisma<\/code> \u2014 database schema &amp; connection <\/p>\n<\/li>\n<li>\n<p><code>.env<\/code> \u2014 environment variables <\/p>\n<\/li>\n<li>\n<p><code>prisma.config.ts<\/code> \u2014 project config <\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h2>\u2699\ufe0fConfigure MySQL<\/h2>\n<p>By default Prisma uses PostgreSQL or SQLite. We switch to MySQL. Now open <code>.env<\/code>:<\/p>\n<pre><code>DATABASE_URL=\"mysql:\/\/root:password@localhost:3306\/my_db\"DATABASE_USER=\"root\"DATABASE_PASSWORD=\"password\"DATABASE_NAME=\"my_db\"DATABASE_HOST=\"localhost\"DATABASE_PORT=3306<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>And now open schema.prisma:<\/p>\n<pre><code class=\"typescript\">generator client {  provider = \"prisma-client\"  output   = \"..\/generated\/prisma\"  moduleFormat  = \"cjs\"}datasource db {  provider = \"mysql\"}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>This is the standard connection format for MySQL in Prisma <\/p>\n<hr\/>\n<h2>\ud83e\udde0 Generate Prisma Client<\/h2>\n<pre><code class=\"bash\">npx prisma generate<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\ud83d\udc49 Prisma generates a <strong>type-safe client<\/strong> based on your schema.<br \/> This means your queries are validated at compile time.<\/p>\n<hr\/>\n<h2>\ud83e\udde9Create PrismaService<\/h2>\n<pre><code class=\"typescript\">import \"dotenv\/config\";import { PrismaMariaDb } from \"@prisma\/adapter-mariadb\";import { PrismaClient } from \"..\/generated\/prisma\/client\";import { Injectable } from \"@nestjs\/common\";@Injectable()export class PrismaService extends PrismaClient{    constructor(){        const adapter = new PrismaMariaDb({        host: process.env.DATABASE_HOST,        user: process.env.DATABASE_USER,        password: process.env.DATABASE_PASSWORD,        database: process.env.DATABASE_NAME,        connectionLimit: 5,        });        super({adapter})    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\ud83d\udca1 Why this is needed:<\/p>\n<ul>\n<li>\n<p> integrates Prisma into Nest lifecycle <\/p>\n<\/li>\n<li>\n<p> ensures proper connection handling <\/p>\n<\/li>\n<li>\n<p> avoids memory leaks in production <\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h2>\ud83e\udde9Create PrismaModule<\/h2>\n<pre><code class=\"typescript\">import { Module } from '@nestjs\/common';import { PrismaService } from '.\/prisma.service';@Module({  providers: [PrismaService],  exports: [PrismaService],})export class PrismaModule {}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<hr\/>\n<h2>\ud83d\udd0cUse Prisma in your service<\/h2>\n<p>We\u2019ll write our service in the constructor. I\u2019ll show you how to use it with an example:<\/p>\n<pre><code class=\"typescript\">import { Injectable } from '@nestjs\/common';import { PrismaService } from 'prisma\/prisma.service';import { TodoDTO } from '.\/dto\/todo.dto';@Injectable()export class TodoService {    constructor(private readonly todoService: PrismaService){} \/\/this is mandatory    public getOne(id:number){        return this.todoService.todo.findFirst(            {                where: {id}            }        )    }    public getAll(){        return this.todoService.todo.findMany()    }    public create(data: TodoDTO){        return this.todoService.todo.create({data: data})    }    public upgrade(id: number, data: TodoDTO){        return this.todoService.todo.update({            where: {id},            data: data        })    }    public delete(id:number){        return  this.todoService.todo.delete(            {                where: {id}            }        )    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\ud83d\udccc This is how Prisma is typically used in NestJS services <\/p>\n<hr\/>\n<h2>\ud83d\udd25Run migrations<\/h2>\n<pre><code class=\"bash\">npx prisma migrate dev --name initnpx prisma generate<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\ud83e\udde9 Monorepo setup (short explanation)<\/h2>\n<p>In a monorepo:<\/p>\n<ul>\n<li>\n<p> keep Prisma in a <strong>separate package\/lib<\/strong> <\/p>\n<\/li>\n<li>\n<p> export only services (not raw client) <\/p>\n<\/li>\n<li>\n<p> reuse across apps <\/p>\n<\/li>\n<\/ul>\n<p>This helps:<\/p>\n<ul>\n<li>\n<p> isolate DB logic <\/p>\n<\/li>\n<li>\n<p> simplify scaling <\/p>\n<\/li>\n<li>\n<p> switch databases easier<\/p>\n<\/li>\n<\/ul>\n<h2>\ud83d\udcda Bonus \u2014 Official docs<\/h2>\n<ul>\n<li>\n<p><a href=\"https:\/\/nestjs.com\/\" rel=\"noopener noreferrer nofollow\">NestJS<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.prisma.io\/\" rel=\"noopener noreferrer nofollow\">Prisma<\/a><\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26a\/503\/77e\/26a50377e7947421c9158ae61064d34e.png\" width=\"1024\" height=\"1536\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/26a\/503\/77e\/26a50377e7947421c9158ae61064d34e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26a\/503\/77e\/26a50377e7947421c9158ae61064d34e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>Also, especially for you, I\u2019ve included a reference card so you can remember and save it for future use. In this card, I\u2019ve gathered all the material to make things easier for you.<\/p>\n<p>If this guide helped you \u2014 feel free to support the post.<br \/> <em>Thanks for your attention!<\/em><\/p>\n<p><strong>Author: Starikov Maxim<\/strong><\/p>\n<p>\u00a0<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1033396\/\">https:\/\/habr.com\/ru\/articles\/1033396\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi! While working on a backend project, I ran into a simple but annoying problem \u2014 I couldn\u2019t find a clear and complete guide on connecting MySQL to a basic backend project.Most tutorials either: skip important steps  assume too much prior knowledge  or don\u2019t explain why things work the way they do So in this guide, I\u2019ll show you: how to connect MySQL using NestJS + Prisma  how it works under the hood  and how to use it in a monorepo setup \ud83d\udccc Why Prisma?Before we start \u2014 a quick note.Prisma is not just another ORM. It provides:type-safe database queries  auto-generated client based on schema  better developer experience than classic ORMs like TypeORM In simple terms: less SQL, fewer runtime errors, more productivity.Create a NestJS projectnpm i -g @nestjs\/clinest new my-backend-projectcd my-backend-projectnpm installRun it:npm run startInstall Prismanpm install prisma &#8212;save-devnpm install @prisma\/clientInitialize Prisma:npx prisma init\ud83d\udca1 Best practice: always use npx prisma instead of global CLI \ud83d\udcc1 After initialization, you\u2019ll get:schema.prisma \u2014 database schema &amp; connection .env \u2014 environment variables prisma.config.ts \u2014 project config \u2699\ufe0fConfigure MySQLBy default Prisma uses PostgreSQL or SQLite. We switch to MySQL. Now open .env:DATABASE_URL=&#187;mysql:\/\/root:password@localhost:3306\/my_db&#187;DATABASE_USER=&#187;root&#187;DATABASE_PASSWORD=&#187;password&#187;DATABASE_NAME=&#187;my_db&#187;DATABASE_HOST=&#187;localhost&#187;DATABASE_PORT=3306And now open schema.prisma:generator client {  provider = &#171;prisma-client&#187;  output   = &#171;..\/generated\/prisma&#187;  moduleFormat  = &#171;cjs&#187;}datasource db {  provider = &#171;mysql&#187;}This is the standard connection format for MySQL in Prisma \ud83e\udde0 Generate Prisma Clientnpx prisma generate\ud83d\udc49 Prisma generates a type-safe client based on your schema. This means your queries are validated at compile time.\ud83e\udde9Create PrismaServiceimport &#171;dotenv\/config&#187;;import { PrismaMariaDb } from &#171;@prisma\/adapter-mariadb&#187;;import { PrismaClient } from &#171;..\/generated\/prisma\/client&#187;;import { Injectable } from &#171;@nestjs\/common&#187;;@Injectable()export class PrismaService extends PrismaClient{    constructor(){        const adapter = new PrismaMariaDb({        host: process.env.DATABASE_HOST,        user: process.env.DATABASE_USER,        password: process.env.DATABASE_PASSWORD,        database: process.env.DATABASE_NAME,        connectionLimit: 5,        });        super({adapter})    }}\ud83d\udca1 Why this is needed: integrates Prisma into Nest lifecycle  ensures proper connection handling  avoids memory leaks in production \ud83e\udde9Create PrismaModuleimport { Module } from &#8216;@nestjs\/common&#8217;;import { PrismaService } from &#8216;.\/prisma.service&#8217;;@Module({  providers: [PrismaService],  exports: [PrismaService],})export class PrismaModule {}\ud83d\udd0cUse Prisma in your serviceWe\u2019ll write our service in the constructor. I\u2019ll show you how to use it with an example:import { Injectable } from &#8216;@nestjs\/common&#8217;;import { PrismaService } from &#8216;prisma\/prisma.service&#8217;;import { TodoDTO } from &#8216;.\/dto\/todo.dto&#8217;;@Injectable()export class TodoService {    constructor(private readonly todoService: PrismaService){} \/\/this is mandatory    public getOne(id:number){        return this.todoService.todo.findFirst(            {                where: {id}            }        )    }    public getAll(){        return this.todoService.todo.findMany()    }    public create(data: TodoDTO){        return this.todoService.todo.create({data: data})    }    public upgrade(id: number, data: TodoDTO){        return this.todoService.todo.update({            where: {id},            data: data        })    }    public delete(id:number){        return  this.todoService.todo.delete(            {                where: {id}            }        )    }}\ud83d\udccc This is how Prisma is typically used in NestJS services \ud83d\udd25Run migrationsnpx prisma migrate dev &#8212;name initnpx prisma generate\ud83e\udde9 Monorepo setup (short explanation)In a monorepo: keep Prisma in a separate package\/lib  export only services (not raw client)  reuse across apps This helps: isolate DB logic  simplify scaling  switch databases easier\ud83d\udcda Bonus \u2014 Official docsNestJSPrismaAlso, especially for you, I\u2019ve included a reference card so you can remember and save it for future use. In this card, I\u2019ve gathered all the material to make things easier for you.If this guide helped you \u2014 feel free to support the post. Thanks for your attention!Author: Starikov Maxim\u00a0\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/habr.com\/ru\/articles\/1033396\/<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-479173","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=479173"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479173\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=479173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=479173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=479173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}