What if your database could update itself perfectly every time you change your app?
Why Migrations in NestJS? - Purpose & Use Cases
Imagine you have a growing app and you need to change your database structure by hand every time you add a new feature.
You open your database tool and manually add or remove columns, tables, or indexes for each update.
Manually changing the database is slow and risky.
You might forget a step, make a typo, or apply changes in the wrong order.
This can break your app or cause data loss, especially when working with a team.
Migrations automate database changes in a safe, repeatable way.
They keep track of what changes were made and apply them in order.
This means your database stays in sync with your app code without manual errors.
ALTER TABLE users ADD COLUMN age INT;
await queryRunner.addColumn('users', new TableColumn({ name: 'age', type: 'int' }));
Migrations let you evolve your database confidently as your app grows, even with multiple developers.
When your team adds a new feature that needs a new table, migrations let everyone update their databases with one command, avoiding confusion and errors.
Manual database changes are error-prone and hard to track.
Migrations automate and organize database updates safely.
This keeps your app and database in sync as you develop.
Practice
Solution
Step 1: Understand what migrations do
Migrations help change the database structure safely without losing data.Step 2: Identify the correct purpose in NestJS context
They are not for business logic or HTTP handling but for database schema updates.Final Answer:
To safely update the database schema step-by-step -> Option BQuick Check:
Migrations = safe database updates [OK]
- Confusing migrations with business logic
- Thinking migrations handle HTTP requests
- Assuming migrations manage authentication
Solution
Step 1: Recall commands for migrations
migration:runapplies pending migrations to the database.Step 2: Differentiate from other commands
migration:createcreates a new migration file,migration:generategenerates migration from schema changes, andmigration:revertundoes the last migration.Final Answer:
npx typeorm migration:run -> Option DQuick Check:
Run migrations = migration:run [OK]
- Using migration:create to run migrations
- Confusing migration:generate with migration:run
- Using migration:revert to apply migrations
up() is run?export class AddAgeColumn1678901234567 {
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE users ADD COLUMN age int`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE users DROP COLUMN age`);
}
}Solution
Step 1: Analyze the up() method
Theup()method runs SQL to add a column named 'age' of type integer to the 'users' table.Step 2: Understand the effect of the query
This modifies the existing 'users' table by adding the new column; it does not remove columns or create new tables.Final Answer:
Adds a new integer column 'age' to the 'users' table -> Option CQuick Check:
up() adds column 'age' [OK]
- Confusing up() with down() method
- Thinking it creates a new table
- Assuming syntax error due to semicolons
npx typeorm migration:run. What is the likely problem?export class RemoveEmailColumn1678901234568 {
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE users DROP email`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE users ADD email varchar(255)`);
}
}Solution
Step 1: Check the SQL in up() method
The queryALTER TABLE users DROP emailis incorrect SQL syntax for dropping a column.Step 2: Correct SQL syntax for dropping a column
The correct syntax isALTER TABLE users DROP COLUMN email. Missing 'COLUMN' causes the error.Final Answer:
The SQL syntax for dropping a column is incorrect -> Option AQuick Check:
DROP COLUMN keyword required in SQL [OK]
- Omitting COLUMN keyword in DROP statement
- Assuming class name causes error
- Forgetting async keyword (not the cause here)
up() and down() methods are correct?Solution
Step 1: Identify correct SQL syntax for renaming columns
The standard SQL syntax supported by many databases isALTER TABLE table_name RENAME COLUMN old_name TO new_name.Step 2: Check each option's SQL correctness and revert logic
async up(queryRunner) { await queryRunner.query(`ALTER TABLE accounts RENAME COLUMN username TO user_name`); } async down(queryRunner) { await queryRunner.query(`ALTER TABLE accounts RENAME COLUMN user_name TO username`); }uses correct syntax for both up() and down() to rename and revert the column name.async up(queryRunner) { await queryRunner.query(`ALTER TABLE accounts CHANGE username user_name varchar(255)`); } async down(queryRunner) { await queryRunner.query(`ALTER TABLE accounts CHANGE user_name username varchar(255)`); }uses MySQL-specific CHANGE syntax which may not be portable.async up(queryRunner) { await queryRunner.query(`ALTER TABLE accounts DROP COLUMN username`); await queryRunner.query(`ALTER TABLE accounts ADD COLUMN user_name varchar(255)`); } async down(queryRunner) { await queryRunner.query(`ALTER TABLE accounts DROP COLUMN user_name`); await queryRunner.query(`ALTER TABLE accounts ADD COLUMN username varchar(255)`); }drops and adds columns, losing data.async up(queryRunner) { await queryRunner.query(`RENAME COLUMN username TO user_name`); } async down(queryRunner) { await queryRunner.query(`RENAME COLUMN user_name TO username`); }misses the table name in the query, causing error.Final Answer:
ALTER TABLE accounts RENAME COLUMN username TO user_name -> Option AQuick Check:
Rename column with ALTER TABLE RENAME COLUMN [OK]
- Dropping and adding columns instead of renaming
- Omitting table name in ALTER TABLE
- Using database-specific syntax without checking compatibility
Ready to prove it?
Pass the test and this pattern moves unknown
