ื“ืœื’ ืœืชื•ื›ืŸ ื”ืจืืฉื™

Migrations

Database migrations manage schema changes across environments in a controlled, versioned manner.

Overviewโ€‹

ORMMigration SystemDirectory
TypeORMTypeORM migrationspackages/core/src/lib/database/migrations/
MikroORMMikroORM migrationspackages/core/src/lib/database/migrations/
KnexKnex migrationspackages/core/src/lib/database/knex-migrations/

TypeORM Migrationsโ€‹

Generate a Migrationโ€‹

# Auto-generate from entity changes
yarn typeorm migration:generate -n AddEmployeeSkillsColumn

TypeORM compares the current entity definitions with the database schema and generates the necessary SQL.

Create an Empty Migrationโ€‹

# Create empty migration shell
yarn typeorm migration:create -n CustomMigration

Migration File Formatโ€‹

import { MigrationInterface, QueryRunner } from "typeorm";

export class AddEmployeeSkillsColumn1704067200000
implements MigrationInterface
{
name = "AddEmployeeSkillsColumn1704067200000";

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "employee"
ADD COLUMN "skills" text
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "employee"
DROP COLUMN "skills"
`);
}
}

Running Migrationsโ€‹

# Run all pending migrations
yarn typeorm migration:run

# Revert the last migration
yarn typeorm migration:revert

# Show migration status
yarn typeorm migration:show

Database-Specific Migrationsโ€‹

Migrations are organized by database type:

packages/core/src/lib/database/migrations/
โ”œโ”€โ”€ postgres/ # PostgreSQL-specific migrations
โ”œโ”€โ”€ mysql/ # MySQL-specific migrations
โ””โ”€โ”€ sqlite/ # SQLite-specific migrations

MikroORM Migrationsโ€‹

Generate a Migrationโ€‹

yarn mikro-orm migration:create --initial     # First migration
yarn mikro-orm migration:create # Subsequent migrations

Running Migrationsโ€‹

yarn mikro-orm migration:up                   # Run pending
yarn mikro-orm migration:down # Revert last
yarn mikro-orm migration:list # Show status
yarn mikro-orm migration:fresh # Drop all & re-run (dev only)

Knex Migrationsโ€‹

Creating a Knex Migrationโ€‹

yarn knex migrate:make migration_name

Knex Migration Formatโ€‹

import { Knex } from "knex";

export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable("custom_table", (table) => {
table.uuid("id").primary().defaultTo(knex.raw("uuid_generate_v4()"));
table.string("name").notNullable();
table.uuid("tenant_id").notNullable().references("tenant.id");
table.timestamps(true, true);
});
}

export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTable("custom_table");
}

Running Knex Migrationsโ€‹

yarn knex migrate:latest          # Run all pending
yarn knex migrate:rollback # Rollback last batch
yarn knex migrate:status # Show status

Migration Best Practicesโ€‹

DOโ€‹

  • โœ… Always write both up and down methods
  • โœ… Test migrations against all supported databases (PostgreSQL, MySQL, SQLite)
  • โœ… Include tenantId columns and foreign keys for new tables
  • โœ… Use transactions for data migrations
  • โœ… Name migrations descriptively with timestamps

DON'Tโ€‹

  • โŒ Use DB_SYNCHRONIZE=true in production
  • โŒ Modify existing migrations (create new ones instead)
  • โŒ Delete migration files from version control
  • โŒ Run production migrations without backup

Production Checklistโ€‹

  1. โœ… Backup the database
  2. โœ… Run migrations in staging first
  3. โœ… Verify migration:show status
  4. โœ… Monitor migration execution time
  5. โœ… Test rollback procedure

Configurationโ€‹

# Auto-synchronize (development only!)
DB_SYNCHRONIZE=false

# Migration logging
DB_LOGGING=schema,migration