Does NestJS Work With MySQL?
NestJS and MySQL work together seamlessly via TypeORM or Prisma, making this a production-ready combination for enterprise Node.js applications.
Quick Facts
How NestJS Works With MySQL
NestJS integrates with MySQL through database abstraction layers, primarily TypeORM (the most common choice) or Prisma. TypeORM is tightly integrated into NestJS via @nestjs/typeorm, providing decorators for entity definitions, repositories, and automatic dependency injection. This means you define your MySQL tables as TypeScript classes with @Entity() decorators, then inject repositories into services for type-safe database operations. The developer experience is exceptional—migrations, relationships, and transactions feel native to the framework. Prisma offers an alternative with a modern schema-driven approach and superior DX for many teams. Both ORMs handle connection pooling, query building, and MySQL-specific features like JSON columns. Architecture-wise, you'll structure your app with entities, repositories, services, and controllers following NestJS patterns, keeping data access logic cleanly separated. MySQL 5.7+ is production-ready, though 8.0+ is recommended for better performance and features.
Best Use Cases
Quick Setup
npm install @nestjs/typeorm typeorm mysql2// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
import { UserService } from './user.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'password',
database: 'myapp',
entities: [User],
synchronize: true,
}),
TypeOrmModule.forFeature([User]),
],
providers: [UserService],
})
export class AppModule {}
// user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
email: string;
@Column()
name: string;
}
// user.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
async findAll(): Promise<User[]> {
return this.usersRepository.find();
}
}Known Issues & Gotchas
Connection pool exhaustion under load if not configured properly
Fix: Set appropriate pool size (default 10) in TypeOrmModule config and monitor active connections in production
N+1 query problems when loading related entities without proper eager loading
Fix: Use leftJoinAndSelect() in QueryBuilder or load relations explicitly; enable query logging in development to catch issues
Type mismatches between TypeScript and MySQL column types (especially dates, decimals)
Fix: Use @Column() type hints explicitly (e.g., @Column('decimal', { precision: 10, scale: 2 })) and leverage transformer option for custom serialization
Timezone handling—MySQL stores UTC but Node.js may misinterpret datetime without explicit config
Fix: Always use serverTimezone='+00:00' in connection config and store timestamps as UTC
Alternatives
- •NestJS + PostgreSQL: More advanced features (JSONB, arrays), slightly better performance for complex queries
- •NestJS + MongoDB: Document-oriented, better for unstructured data, trades ACID guarantees for schema flexibility
- •Express + Sequelize + MySQL: Lighter alternative without NestJS overhead, less opinionated structure
Resources
Related Compatibility Guides
Explore more compatibility guides