Agent Skills: Create Database Migration

Create database migrations from templates in the Commons monorepo. Use when the user wants to create a migration, add database columns, create tables, or modify the database schema.

UncategorizedID: jakewaldrip/.dotfiles/database-migration

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jakewaldrip/.dotfiles/tree/HEAD/misc/commons/.opencode/skills/database-migration

Skill Files

Browse the full folder contents for database-migration.

Download Skill

Loading file tree…

misc/commons/.opencode/skills/database-migration/SKILL.md

Skill Metadata

Name
database-migration
Description
Create database migrations from templates in the Commons monorepo. Use when the user wants to create a migration, add database columns, create tables, or modify the database schema.

Create Database Migration

When to Use

Schema changes only: adding/removing/modifying columns, tables, indexes, or feature flags.

When NOT to Use

Patient data operations (backfilling, updating, transforming data) → Use commons-packages/backend/jobs/ instead.

Create a Migration

npm run migrate:make <name-of-migration>

Creates file in commons-packages/backend/models/migrations/YYYYMMDDHHMMSS_name-of-migration.ts

Common Patterns

Standard Table Columns

table.uuid('id').primary().defaultTo(knex.raw('uuid_generate_v4()'));
table.timestamp('createdAt').defaultTo(knex.raw('now()')).notNullable();
table.timestamp('updatedAt').defaultTo(knex.raw('now()')).notNullable();

Soft Delete Columns

table.timestamp('deletedAt');
table.uuid('deletedById').references('id').inTable('user').onDelete('SET NULL').nullable();
table.index(['deletedById'], `${TABLE_NAME}_deleted_by_id_idx`);

Audit Columns

table.uuid('createdById').references('id').inTable('user').onDelete('SET NULL').nullable();
table.uuid('updatedById').references('id').inTable('user').onDelete('SET NULL').nullable();

Foreign Key with Index

table.uuid('patientId').references('id').inTable('patient').onDelete('CASCADE').notNullable();
table.index(['patientId'], `${TABLE_NAME}_patient_id_idx`);

Partial Index (for soft-deleted tables)

table.index(['columnName'], `${TABLE_NAME}_column_name_idx`, {
  predicate: knex.whereNull('deletedAt'),
});

Enum Column (type-safe)

// Import TYPE only, hardcode values to prevent future breakage
import type { MyStatus } from '@commons/shared/graphql/enums/my-status.enum';

const VALUES = ['open', 'closed'] as const satisfies readonly MyStatus[];
table.enum('status', VALUES).notNullable();

Validation

# Run pending migrations
npm run migrate

# Test rollback
npm run migrate:rollback

Best Practices

  • Always implement both up and down for rollback capability
  • Check table existence before operations: await knex.schema.hasTable(TABLE_NAME)
  • Add indexes for foreign keys to improve query performance
  • Use CASCADE DELETE carefully—consider orphaned records in rollback
  • For column removal: Rename to drop_* first, then drop in a later migration

Templates and Examples

  • Templates: commons-packages/backend/models/migrations/examples/
  • See TEMPLATES.md for additional patterns and helper functions