Skip to main content

DATABASE MIGRATION

database-migration.ts

Safe migrations: backward-compatible adds, batched ops, rollback.

Stark avatarStark

WHAT THIS PATTERN TEACHES

How to run safe database migrations: add columns as nullable first, backfill then constrain, batch large table operations, test rollbacks. Every migration has a tested down migration.

WHEN TO USE THIS

Any schema change in production — adding columns, creating indexes, removing fields, renaming tables.

AT A GLANCE

// Safe column add: nullable first, backfill, constrain
await db.schema.alterTable('users', (t) => {
  t.string('email_verified').nullable();
});
await batchUpdate('users', setDefault);

FRAMEWORK IMPLEMENTATIONS

TypeScript
interface Migration {
  version: string;
  up: (db: Database) => Promise<void>;
  down: (db: Database) => Promise<void>;
}

async function batchUpdate(
  table: string,
  update: (batch: Row[]) => Row[],
  batchSize = 1000
) {
  let offset = 0;
  while (true) {
    const rows = await db.select(table, { limit: batchSize, offset });
    if (rows.length === 0) break;
    await db.updateBatch(table, update(rows));
    offset += batchSize;
  }
}
← All Patterns