How to run migrations in Node.js

Running migrations in Node.js enables version-controlled database schema changes that ensure consistent database structure across development, staging, and production environments. As the creator of CoreUI with extensive Node.js experience since 2014, I’ve implemented migration systems in numerous enterprise applications for safe database evolution and team collaboration. The most reliable approach uses migration frameworks like Sequelize CLI or dedicated migration tools to create, run, and rollback database changes systematically. This method provides database versioning with rollback capabilities while maintaining data integrity and enabling team-wide schema synchronization.

Use Sequelize CLI to create and run migrations for systematic database schema management in Node.js applications.

// Install and setup Sequelize CLI
// npm install --save-dev sequelize-cli
// npx sequelize-cli init

// sequelize-cli configuration in config/config.js
module.exports = {
    development: {
        username: 'root',
        password: 'password',
        database: 'myapp_dev',
        host: '127.0.0.1',
        dialect: 'postgres'
    },
    production: {
        username: process.env.DB_USER,
        password: process.env.DB_PASS,
        database: process.env.DB_NAME,
        host: process.env.DB_HOST,
        dialect: 'postgres'
    }
}

// Create migration file: npx sequelize-cli migration:generate --name create-users-table
// Generated migration file: migrations/20251208120000-create-users-table.js

'use strict'

module.exports = {
    async up(queryInterface, Sequelize) {
        await queryInterface.createTable('Users', {
            id: {
                allowNull: false,
                autoIncrement: true,
                primaryKey: true,
                type: Sequelize.INTEGER
            },
            email: {
                type: Sequelize.STRING,
                allowNull: false,
                unique: true
            },
            firstName: {
                type: Sequelize.STRING,
                allowNull: false
            },
            lastName: {
                type: Sequelize.STRING,
                allowNull: false
            },
            password: {
                type: Sequelize.STRING,
                allowNull: false
            },
            createdAt: {
                allowNull: false,
                type: Sequelize.DATE,
                defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
            },
            updatedAt: {
                allowNull: false,
                type: Sequelize.DATE,
                defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
            }
        })

        // Add indexes
        await queryInterface.addIndex('Users', ['email'])
        await queryInterface.addIndex('Users', ['createdAt'])
    },

    async down(queryInterface, Sequelize) {
        await queryInterface.dropTable('Users')
    }
}

// Create another migration: npx sequelize-cli migration:generate --name add-role-to-users
// migrations/20251208130000-add-role-to-users.js

'use strict'

module.exports = {
    async up(queryInterface, Sequelize) {
        await queryInterface.addColumn('Users', 'role', {
            type: Sequelize.ENUM('admin', 'user', 'moderator'),
            allowNull: false,
            defaultValue: 'user'
        })

        // Update existing users to have default role
        await queryInterface.bulkUpdate('Users', {
            role: 'user'
        }, {})
    },

    async down(queryInterface, Sequelize) {
        await queryInterface.removeColumn('Users', 'role')
    }
}

// Migration runner script: scripts/migrate.js
const { Sequelize } = require('sequelize')
const { Umzug, SequelizeStorage } = require('umzug')

async function runMigrations() {
    const sequelize = new Sequelize(process.env.DATABASE_URL)

    const umzug = new Umzug({
        migrations: {
            glob: 'migrations/*.js',
            resolve: ({ name, path, context }) => {
                const migration = require(path)
                return {
                    name,
                    up: async () => migration.up(context.queryInterface, Sequelize),
                    down: async () => migration.down(context.queryInterface, Sequelize)
                }
            }
        },
        context: { queryInterface: sequelize.getQueryInterface() },
        storage: new SequelizeStorage({ sequelize }),
        logger: console
    })

    try {
        await umzug.up()
        console.log('All migrations completed successfully')
    } catch (error) {
        console.error('Migration failed:', error)
        process.exit(1)
    } finally {
        await sequelize.close()
    }
}

// Package.json scripts
{
    "scripts": {
        "db:migrate": "npx sequelize-cli db:migrate",
        "db:migrate:undo": "npx sequelize-cli db:migrate:undo",
        "db:migrate:undo:all": "npx sequelize-cli db:migrate:undo:all",
        "db:create": "npx sequelize-cli db:create",
        "db:drop": "npx sequelize-cli db:drop"
    }
}

This code demonstrates comprehensive migration setup using Sequelize CLI with proper up/down migration methods, configuration management, and automated migration running. The system tracks migration history, enables rollbacks, and provides consistent schema changes across environments. Migration files include table creation, column additions, index management, and data updates with proper error handling and transaction support.

Best Practice Note:

This is the migration strategy we implement in CoreUI enterprise backend services for safe, version-controlled database evolution. Always test migrations in development, include rollback procedures, and backup production databases before running migrations in production environments.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
Dealing with Sass Deprecation Warnings in Angular 19
Dealing with Sass Deprecation Warnings in Angular 19

The Best Bootstrap Alternative for Developers in 2025
The Best Bootstrap Alternative for Developers in 2025

How to Remove Underline from Link in CSS
How to Remove Underline from Link in CSS

How to Achieve Perfectly Rounded Corners in CSS
How to Achieve Perfectly Rounded Corners in CSS

Answers by CoreUI Core Team