Migration Module
November 19, 2025 ยท View on GitHub
The migration module for Hexabot provides a simple and effective way to manage database migrations powered by TypeORM. It allows you to create, execute, and roll back migrations, ensuring the database schema stays in sync with the version DB updates.
Whenever a new version is released which requires some DB updates, the onApplicationBootstrap() lifecycle hook
will apply migrations automatically when config.database.autoMigrate is enabled (by default this is true outside production, or when the environment variables opt-in).
Features
- Generate timestamped migration files automatically in kebab-case.
- Track migration execution status in the relational
hexabot_migrationstable. - Run individual or all migrations with ease.
- Built-in support for rollback logic.
- Keeps track of the database schema version in the metadata table (SettingModule).
Usage
Creating a Migration
To create a new migration:
pnpm --filter @hexabot-ai/api run cli migration create <version>
Replace <version> with the next version for your migration, such as v3.0.1.
Example:
pnpm --filter @hexabot-ai/api run cli migration create v3.0.1
This will generate a new file under src/migration/migrations/ with a timestamped filename in kebab-case.
Running Migrations
Running a Specific Migration
To execute a specific migration, use:
pnpm --filter @hexabot-ai/api run cli migration migrate up <version>
Example:
pnpm --filter @hexabot-ai/api run cli migration migrate up v3.0.1
Rolling Back a Specific Migration
To roll back a specific migration, use:
pnpm --filter @hexabot-ai/api run cli migration migrate down <version>
Example:
pnpm --filter @hexabot-ai/api run cli migration migrate down v3.0.1
Running All Migrations
To execute all pending migrations:
pnpm --filter @hexabot-ai/api run cli migration migrate up
Rolling Back All Migrations
To roll back all migrations:
pnpm --filter @hexabot-ai/api run cli migration migrate down
Tracking Migration Status
The migration status is stored in the hexabot_migrations table managed by TypeORM. This table helps ensure that each migration is executed or rolled back only once, avoiding duplicate operations.
Example Migration File
Below is an example migration file:
import { MigrationInterface, QueryRunner } from 'typeorm';
import { MigrationServices } from '../types';
export default class Migration1700000000000_V2_2_0 implements MigrationInterface {
name = 'Migration1700000000000_V2_2_0';
public async up(
queryRunner: QueryRunner,
_services?: MigrationServices,
): Promise<void> {
await queryRunner.query(
`UPDATE attachment SET type = 'text/csv' WHERE type = 'csv'`,
);
}
public async down(
queryRunner: QueryRunner,
_services?: MigrationServices,
): Promise<void> {
await queryRunner.query(
`UPDATE attachment SET type = 'csv' WHERE type = 'text/csv'`,
);
}
}
Explanation
upMethod: Defines the operations to apply the migration (e.g., running SQL statements through the query runner).downMethod: Defines the rollback logic to revert the migration.
Best Practices
- Use semantic versioning (e.g.,
v3.0.1) for your migration names to keep track of changes systematically. - Always test migrations in a development or staging environment before running them in production.
- Keep the
upanddownmethods idempotent to avoid side effects from repeated execution.