Database Migrations

Learn how to use the built-in migration tools for database schema changes.

Introduction to Migrations

Database migrations are a way to manage changes to your database schema over time. @inceptools/db provides built-in migration tools for both MongoDB and SQL databases.

Migrations allow you to:

  • Track changes to your database schema
  • Apply changes incrementally
  • Roll back changes if needed
  • Collaborate with team members on database changes
  • Deploy database changes consistently across environments
MongoDB Migration Setup
import { MongoService, SUPPORTED_DBS } from "@inceptools/db";
import mongoose from "mongoose";

// Create a MongoDB service instance
const mongoService = new MongoService({
  type: SUPPORTED_DBS.MONGO_DB,
  connectionString: "mongodb://localhost:27017/myapp",
  models: {},
});

// Connect to MongoDB
await mongoService.connect();

// Get the migration service
const migrationService = mongoService.migrationService;

// Initialize migrations (creates the migrations collection if it doesn't exist)
await migrationService.init();

// Generate a new migration
await migrationService.generateMigration("add-user-roles");
// This creates a file in ./migrations/mongodb/[timestamp]_add-user-roles.js

// Apply pending migrations
await migrationService.migrate();

// Roll back the last applied migration
await migrationService.rollback();

// Get migration status
const status = await migrationService.status();
console.log(status);

MongoDB Migration File Structure

// migrations/mongodb/20230101000000_add-user-roles.js
module.exports = {
  async up(db) {
    // Update schema
    await db.collection('users').updateMany({}, {
      $set: { roles: ['user'] }
    });
  },

  async down(db) {
    // Revert changes
    await db.collection('users').updateMany({}, {
      $unset: { roles: "" }
    });
  }
};
MongoDB Migration Examples
Example 1

Adding a field with a default value

module.exports = {
  async up(db) {
    await db.collection('users').updateMany(
      { isActive: { $exists: false } },
      { $set: { isActive: true } }
    );
  },

  async down(db) {
    await db.collection('users').updateMany(
      {},
      { $unset: { isActive: "" } }
    );
  }
};
Example 2

Creating an index

module.exports = {
  async up(db) {
    await db.collection('users').createIndex(
      { email: 1 },
      { unique: true }
    );
  },

  async down(db) {
    await db.collection('users').dropIndex('email_1');
  }
};
Example 3

Renaming a field

module.exports = {
  async up(db) {
    await db.collection('users').updateMany(
      {},
      { $rename: { "name": "fullName" } }
    );
  },

  async down(db) {
    await db.collection('users').updateMany(
      {},
      { $rename: { "fullName": "name" } }
    );
  }
};
Example 4

Creating a new collection

module.exports = {
  async up(db) {
    await db.createCollection('orders');
    await db.collection('orders').createIndex(
      { userId: 1, createdAt: -1 }
    );
  },

  async down(db) {
    await db.collection('orders').drop();
  }
};

Migration Best Practices

  • Keep migrations small and focused: Each migration should make a single logical change to the database schema.
  • Always implement the down method: This allows you to roll back changes if needed.
  • Test migrations before applying them to production: Run migrations in a development or staging environment first.
  • Use transactions for SQL migrations: This ensures that all changes in a migration are applied atomically.
  • Version control your migrations: Commit migration files to your version control system.
  • Never modify existing migration files: Once a migration has been applied, create a new migration to make additional changes.
  • Document complex migrations: Add comments to explain the purpose and impact of complex changes.

Migration CLI (Coming Soon)

Coming Soon
Command Line Interface

In a future release, @inceptools/db will include a command-line interface for managing migrations:

# Generate a new migration
npx inceptools migrate:generate --name add-user-roles --type mongodb

# Apply pending migrations
npx inceptools migrate:up

# Roll back the last migration
npx inceptools migrate:down

# Get migration status
npx inceptools migrate:status

Stay tuned for updates on the migration CLI!