Hi! While working on a backend project, I ran into a simple but annoying problem — I couldn’t find a clear and complete guide on connecting MySQL to a basic backend project.
Most tutorials either:
Before we start — a quick note.
Prisma is not just another ORM. It provides:
Run it:
npm run start
Initialize Prisma:
npx prisma init
Best practice: always use npx prisma instead of global CLI
By default Prisma uses PostgreSQL or SQLite. We switch to MySQL. Now open .env:
DATABASE_URL="mysql://root
assword@localhost:3306/my_db"
DATABASE_USER="root"
DATABASE_PASSWORD="password"
DATABASE_NAME="my_db"
DATABASE_HOST="localhost"
DATABASE_PORT=3306
And now open schema.prisma:
generator client {
provider = "prisma-client"
output = "../generated/prisma"
moduleFormat = "cjs"
}
datasource db {
provider = "mysql"
}
This is the standard connection format for MySQL in Prisma
npx prisma generate
Prisma generates a type-safe client based on your schema.
This means your queries are validated at compile time.
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})
}
}
Why this is needed:
import { Module } from '@nestjs/common';
import { PrismaService } from './prisma.service';
@Module({
providers: [PrismaService],
exports: [PrismaService],
})
export class PrismaModule {}
We’ll write our service in the constructor. I’ll show you how to use it with an example:
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}
}
)
}
}
This is how Prisma is typically used in NestJS services
npx prisma migrate dev --name initnpx prisma generate
In a monorepo:
Also, especially for you, I’ve included a reference card so you can remember and save it for future use. In this card, I’ve gathered all the material to make things easier for you.
If this guide helped you — feel free to support the post.
Thanks for your attention!
Most tutorials either:
- skip important steps
- assume too much prior knowledge
- or don’t explain why things work the way they do
- how to connect MySQL using NestJS + Prisma
- how it works under the hood
- and how to use it in a monorepo setup
Why Prisma?
Before we start — 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
Create a NestJS project
npm i -g @nestjs/clinest new my-backend-projectcd my-backend-projectnpm installRun it:
npm run start
Install Prisma
npm install prisma --save-devnpm install @prisma/clientInitialize Prisma:
npx prisma init
After initialization, you’ll get:
- schema.prisma — database schema & connection
- .env — environment variables
- prisma.config.ts — project config
Configure MySQL
By default Prisma uses PostgreSQL or SQLite. We switch to MySQL. Now open .env:DATABASE_URL="mysql://root
DATABASE_USER="root"
DATABASE_PASSWORD="password"
DATABASE_NAME="my_db"
DATABASE_HOST="localhost"
DATABASE_PORT=3306
And now open schema.prisma:
generator client {
provider = "prisma-client"
output = "../generated/prisma"
moduleFormat = "cjs"
}
datasource db {
provider = "mysql"
}
This is the standard connection format for MySQL in Prisma
Generate Prisma Client
npx prisma generateThis means your queries are validated at compile time.
Create PrismaService
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})
}
}
- integrates Prisma into Nest lifecycle
- ensures proper connection handling
- avoids memory leaks in production
Create PrismaModule
import { Module } from '@nestjs/common';import { PrismaService } from './prisma.service';
@Module({
providers: [PrismaService],
exports: [PrismaService],
})
export class PrismaModule {}
Use Prisma in your service
We’ll write our service in the constructor. I’ll show you how to use it with an example: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}
}
)
}
}
Run migrations
npx prisma migrate dev --name initnpx prisma generate
Monorepo setup (short explanation)
In a monorepo:- keep Prisma in a separate package/lib
- export only services (not raw client)
- reuse across apps
- isolate DB logic
- simplify scaling
- switch databases easier
Bonus — Official docs
Also, especially for you, I’ve included a reference card so you can remember and save it for future use. In this card, I’ve gathered all the material to make things easier for you.
If this guide helped you — feel free to support the post.
Thanks for your attention!