docs/handbook/engineering/playbooks/database-migration.mdx
Activepieces uses TypeORM as its database driver in Node.js. We support two database types across different editions of our platform.
The database migration files contain both what to do to migrate (up method) and what to do when rolling back (down method).
<Tip> Read more about TypeORM migrations here: https://orkhan.gitbook.io/typeorm/docs/migrations </Tip>PGlite is a lightweight PostgreSQL implementation that runs embedded, so migrations are compatible with PostgreSQL. </Tip>
The generated file uses `MigrationInterface` — you need to update it:
1. Change `implements MigrationInterface` to `implements Migration`
2. Update the import from `typeorm` to import `Migration` from `../../migration`
3. Add `breaking = false` (or `true` if the migration drops columns/tables or transforms data irreversibly)
4. Add `release = '<version>'` matching the upcoming release version (check `package.json` in the repo root)
5. Implement the `down()` method with queries that reverse the `up()` changes (unless `breaking = true`)
6. Register it in `postgres-connection.ts`
```typescript
import { QueryRunner } from 'typeorm'
import { Migration } from '../../migration'
export class AddMyColumn1234567890 implements Migration {
name = 'AddMyColumn1234567890'
breaking = false
release = '0.78.0'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "project" ADD COLUMN "description" text`)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "project" DROP COLUMN "description"`)
}
}
```
CI will fail if `breaking`, `release`, or `down()` are missing on new migrations.
While PGlite is mostly PostgreSQL-compatible, some features are not supported. When using features like CONCURRENTLY for index operations, you need to conditionally handle PGlite:
import { QueryRunner } from 'typeorm'
import { Migration } from '../../migration'
import { system } from '../../../helper/system/system'
import { AppSystemProp } from '../../../helper/system/system-props'
import { DatabaseType } from '../../database-type'
const databaseType = system.get(AppSystemProp.DB_TYPE)
const isPGlite = databaseType === DatabaseType.PGLITE
export class AddMyIndex1234567890 implements Migration {
name = 'AddMyIndex1234567890'
breaking = false
release = '0.78.0'
transaction = false // Required when using CONCURRENTLY
public async up(queryRunner: QueryRunner): Promise<void> {
if (isPGlite) {
await queryRunner.query(`CREATE INDEX "idx_name" ON "table" ("column")`)
} else {
await queryRunner.query(`CREATE INDEX CONCURRENTLY "idx_name" ON "table" ("column")`)
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
if (isPGlite) {
await queryRunner.query(`DROP INDEX "idx_name"`)
} else {
await queryRunner.query(`DROP INDEX CONCURRENTLY "idx_name"`)
}
}
}