Skip to main content
Directus uses database migrations to manage schema changes and system updates. Migrations provide a version-controlled way to modify your database structure and data, ensuring consistency across different environments.

Overview

Migrations in Directus are TypeScript files that define database changes. Each migration has:
  • Version - A unique identifier (timestamp-based)
  • Name - Descriptive name of the migration
  • Up Function - Code to apply the migration
  • Down Function - Code to revert the migration
All migrations are tracked in the directus_migrations table.

Migration Structure

A basic migration file follows this pattern:

System Migrations

Directus includes built-in migrations located in /api/src/database/migrations/. These handle:
  • Creating system tables (users, files, collections, etc.)
  • Adding new features to Directus
  • Modifying system table structures
  • Data transformations for upgrades

Migration Naming Convention

System migrations follow the pattern:
Examples:
  • 20260204A-add-deployment.ts
  • 20260128A-add-collaborative-editing.ts
  • 20251103A-add-ai-settings.ts
The version format is YYYYMMDD{A-Z} where:
  • YYYYMMDD - Date of the migration
  • {A-Z} - Letter suffix for multiple migrations on the same day

Custom Migrations

You can create custom migrations to manage your own schema changes.

Location

Custom migrations are stored in:
Configure a custom path:

Creating a Custom Migration

  1. Create a new file in your migrations directory:
  1. Define the up and down functions:

Custom Migration Format

Custom migrations must:
  • Have a name containing a dash (-)
  • Use .js, .cjs, or .mjs extension
  • Export up and down functions
  • Use valid JavaScript/CommonJS/ESM syntax

Running Migrations

CLI Commands

Run migrations using the Directus CLI:

Programmatic Usage

Run migrations programmatically:

Migration Execution Order

Migrations execute in version order:
  1. System migrations (sorted by version)
  2. Custom migrations (sorted by version)
  3. Combined and deduplicated by version

Migration Examples

Creating Tables

Adding Columns

Modifying Columns

Creating Indexes

Data Migrations

Foreign Key Relationships

Migration Tracking

The directus_migrations table tracks applied migrations: Query applied migrations:

Validation

Migration Validation

Directus validates migrations on startup:

Version Collision Detection

Migrations must have unique versions:

Best Practices

Always Provide Down Migrations

Even if you don’t plan to rollback, always implement the down function:

Test Both Directions

Test that migrations can be applied and reverted:

Keep Migrations Small

Create focused migrations that do one thing well:

Use Transactions

Knex migrations run in transactions by default (except MySQL DDL):

Handle Database Differences

Account for database-specific behaviors:

Document Complex Migrations

Add comments for complex logic:

Avoid Direct Table References

Use the schema builder instead of raw SQL when possible:

Backup Before Migrations

Always backup your database before running migrations in production:

Troubleshooting

Migration Failed Mid-Execution

If a migration fails partway through:
  1. Check the directus_migrations table
  2. If the migration wasn’t recorded, fix the issue and run again
  3. If it was recorded but incomplete, manually revert changes and remove the record

Version Collision Error

Solution: Rename one of the colliding migrations with a different suffix:

Missing Migration File

If a migration is recorded in the database but the file is missing, you can:
  1. Restore the migration file from version control
  2. Or remove the record (risky - only if you’re certain):

Next Steps