Learn how to manage database migrations in NestJS using TypeORM and Sequelize . Understand the process of setting up migrations, running them, and handling database schema changes in your NestJS projects. Plus, get interview questions and answers for backend developer roles.
When you’re working on a project with a database, things can get complicated as your project grows. You might need to change the structure of your database to keep up with new features. This is where database migrations come in. Migrations allow you to manage your database structure changes easily, without losing any data or breaking anything in your app.
In this blog, we’ll look at database migrations in NestJS, a powerful framework for building backend applications. We’ll focus on two popular libraries used in NestJS for working with databases:
- Sequelize (an ORM for SQL databases)
- TypeORM (another ORM for SQL databases)
By the end of this blog, you’ll have a clear understanding of what database migrations are, how to perform them in NestJS, and some important interview questions related to this topic.
Table of Contents
What Are Database Migrations?
Imagine your database is like a big box where all your project’s data is stored. Over time, as your project grows, you may need to add new sections to this box or change the way things are organized inside. Instead of manually changing the box (or database) every time you want to add something new, you can write migrations. Migrations are like a set of instructions that tell the database how to change or update its structure automatically.
Why Do You Need Migrations?
Let’s say you’re working in a team, and your colleague adds a new feature that requires a new column in the database. Instead of telling your colleague to manually add the column (which might lead to mistakes), you can use migrations to automatically update the database structure. This ensures everyone’s database stays consistent and up to date.
Sequelize and TypeORM: The Two Tools
Sequelize and TypeORM are both Object-Relational Mappers (ORMs). These tools help you interact with your database using JavaScript (or TypeScript) code, so you don’t need to write raw SQL queries all the time. They both also support migrations.
Sequelize
Sequelize is a promise-based ORM that works with many SQL databases, including MySQL, PostgreSQL, and SQLite. It’s great for developers who need a flexible and easy-to-use tool to interact with databases.
TypeORM
TypeORM is another popular ORM that works well with SQL databases. It is built to take advantage of TypeScript’s features, making it a good choice if you want to use TypeScript in your NestJS projects.
How to Set Up Migrations in NestJS with Sequelize
Step 1: Install the Required Packages
To use Sequelize in a NestJS project, you need to install the following packages:
npm install --save @nestjs/sequelize sequelize sequelize-typescript pg pg-hstore
Step 2: Set Up the Sequelize Module
In your app.module.ts, you need to import and configure Sequelize.
import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
@Module({
imports: [
SequelizeModule.forRoot({
dialect: 'postgres', // Can be 'mysql', 'postgres', 'sqlite', etc.
host: 'localhost',
port: 5432,
username: 'user',
password: 'password',
database: 'mydatabase',
autoLoadModels: true,
synchronize: false, // Set to false for using migrations
}),
],
})
export class AppModule {}
Step 3: Create a Migration
Once Sequelize is set up, you can create a migration. A migration is like a set of instructions that tells the database how to modify its structure. You can generate migrations using the Sequelize CLI.
Install the Sequelize CLI:
npm install --save-dev sequelize-cli
Generate a migration:
npx sequelize-cli migration:generate --name create-users-table
This command creates a migration file where you can define the changes to your database.
Step 4: Define the Migration
Inside the migration file, you can define the changes you want to make. For example, creating a “users” table:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('users');
},
};
Step 5: Run the Migration
Now that you’ve defined the migration, you can run it to update your database:
npx sequelize-cli db:migrate
This command applies the migration and creates the new table in the database.
How to Set Up Migrations in NestJS with TypeORM
Step 1: Install the Required Packages
To use TypeORM in NestJS, install the following packages:
npm install --save @nestjs/typeorm typeorm pg
Step 2: Set Up TypeORM in Your NestJS Project
In your app.module.ts, import and configure TypeORM:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'user',
password: 'password',
database: 'mydatabase',
entities: [],
synchronize: false, // Set to false for migrations
migrations: [__dirname + '/migrations/**/*{.ts,.js}'],
}),
],
})
export class AppModule {}
Step 3: Create a Migration
You can create migrations using the TypeORM CLI. First, install the TypeORM CLI:
npm install --save-dev typeorm
Generate a migration:
npx typeorm migration:generate -n CreateUsersTable
Step 4: Define the Migration
Inside the migration file, you can define changes to your database, such as creating a “users” table:
import { MigrationInterface, QueryRunner } from 'typeorm';
export class CreateUsersTable1646880812264 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP TABLE users');
}
}
Step 5: Run the Migration
Run the migration with the following command:
npx typeorm migration:run
Interview Questions and Answers
Here are some common interview questions related to database migrations in NestJS:
1. What is a migration in NestJS?
A migration in NestJS is a set of instructions to update the structure of a database. It allows developers to modify the database schema over time without losing data or breaking the application.
2. Why do you need to use migrations in a project?
Migrations are used to ensure that all developers and environments (like production or staging) have the same database structure. They also help with version control for database changes.
3. What are the main differences between Sequelize and TypeORM?
- Sequelize is more flexible and works with several SQL databases (like PostgreSQL, MySQL, and SQLite). It’s more straightforward but can be less powerful when working with complex queries.
- TypeORM is more TypeScript-friendly and offers more advanced features, such as decorators and better support for complex database structures.
4. Can you roll back a migration? How?
Yes, you can roll back a migration using the db:migrate:undo
command in Sequelize or migration:revert
in TypeORM. This will undo the changes made by the last migration.
Companies That Ask About Database Migrations in NestJS
Several companies value knowledge of database migrations and ORMs in NestJS during interviews. Some examples include:
- Turing.com
- Accenture
- Globant
- Capgemini
- Cognizant
These companies often ask about handling database migrations in large-scale applications.
Conclusion
Database migrations are an essential part of maintaining and evolving your database over time. Whether you’re using Sequelize or TypeORM in NestJS, understanding how to create and manage migrations is crucial for any backend developer. This blog has covered the basics of migrations, provided examples, and even included some common interview questions you might encounter.
As you continue to grow as a developer, mastering migrations will help you manage your project’s database more effectively and ensure smooth development processes.