Managing Sequelize Migrations

Understanding the Problem

Database migrations are like chapters in your database's story. Each migration represents a change to your database structure, and sometimes we need to move backward or forward in this story. Just as a writer might need to revise earlier chapters of their book, developers often need to undo or redo database changes.

Think of migrations as a time machine for your database. We need to learn how to:

In our specific case, we have five migration files that create different tables: Colors, Shapes, Cats, Users, and Games. We need to understand how to manage these migrations effectively, including how to run them, undo them selectively, and redo them when needed.

Devising a Plan

  1. Run all pending migrations to set up our database tables
  2. Learn how to undo the most recent migration
  3. Practice redoing migrations that were undone
  4. Understand how to undo all migrations
  5. Master the technique of undoing to a specific migration

Carrying Out the Plan

Step 1: Running All Migrations

Let's start by running all our migrations. This will create all our database tables in the correct order:

npx dotenv sequelize db:migrate

After running this command, Sequelize will execute the 'up' function in each migration file in chronological order:

// Example of what happens when migrations run
// First: 20211008201504-create-color.js creates Colors table
// Then:  20211008225744-create-shapes.js creates Shapes table
// Then:  20211008225902-create-cats.js creates Cats table
// Then:  20211008225940-create-users.js creates Users table
// Finally: 20211008225957-create-games.js creates Games table

Step 2: Undoing the Last Migration

To undo just the most recent migration (in our case, the Games table), we use:

npx dotenv sequelize db:migrate:undo

This command will execute the 'down' function of our last migration:

// From 20211008225957-create-games.js
down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('Games')
}

Step 3: Redoing Migrations

To reapply migrations that were undone, we simply run the migrate command again:

npx dotenv sequelize db:migrate

Sequelize keeps track of which migrations have been run in a special table called 'SequelizeMeta'. When you run migrations, it checks this table to know which migrations need to be executed.

Step 4: Undoing All Migrations

To undo all migrations and start fresh:

npx dotenv sequelize db:migrate:undo:all

Step 5: Undoing to a Specific Migration

To undo migrations up to a specific file, we use the --to flag with dotenv-cli:

npx dotenv sequelize -- db:migrate:undo:all --to 20211008225902-create-cats.js

Notice the extra -- after dotenv. This is crucial for passing flags to the underlying sequelize command.

Looking Back and Learning More

Understanding Migration Order

Migrations run in chronological order based on their timestamp prefixes. This is why our migration files start with numbers like '20211008201504'. When running migrations:

The SequelizeMeta Table

Sequelize uses a special table called SequelizeMeta to track which migrations have been run. Think of it as a checklist where Sequelize marks off each completed migration. This is how it knows:

Real-World Applications

Understanding migration management is crucial in real-world scenarios. Here are some common use cases:

Development Scenarios

Production Scenarios

Best Practices

When working with migrations, keep these principles in mind:

Migration Design

Migration Management

Troubleshooting Common Issues

Here are solutions to common migration challenges: