Skip to content

Database Migrations

CKAN extensions manage database schema changes using Alembic. This ensures database schema updates are tracked, version-controlled, and run cleanly across dev, staging, and production environments.


Migration Layout

Migration folder with all required files will be automatically created by CLI ckan generate migration -p myextension when you create the first migration for plugin.

ckanext-myextension/
├── ckanext/
│   └── myextension/
│       ├── plugin.py
│       └── migration/
│           └── myextension/           # Name of your extension
│               ├── alembic.ini
│               ├── env.py
│               ├── script.py.mako
│               └── versions/          # Individual migration files

Migration Version Table Isolation

Since your extension shares the database with CKAN core and other extensions, it must isolate its migration state. To achieve it, env.py, sets custom version table name. You don't need to change any code, it's autogenerated alongside with the first migration for the plugin.

For every plugin with migrations, there will be a separate table PLUGIN_alembic_version in DB. Do not delete this table, as alembic uses it to track the current state of migrations.

env.py
name = os.path.basename(os.path.dirname(__file__))

# Offline migration configuration
context.configure(
    url=url,
    target_metadata=target_metadata,
    literal_binds=True,
    version_table=f"{name}_alembic_version",  # e.g., 'myextension_alembic_version'
)

Generating Migrations

To generate a new database migration file for your extension, use the ckan generate migration command:

ckan generate migration -p myplugin -m "description_of_migration"
  • -p (or --plugin): The name of your plugin (as registered in your plugin entry points, e.g. myplugin).
  • -m (or --message): A brief description of the schema changes, which becomes part of the generated filename.

The command creates a new Python migration script inside your extension's migration/<plugin_name>/versions/ directory.

Automatic Migration Generation

CKAN's migration generator supports the --autogenerate flag. This option directs Alembic to compare the metadata defined in your Python models (specifically target_metadata inside env.py) with your active database schema, and automatically output the corresponding upgrade/downgrade code:

ckan generate migration -p myplugin -m "add_myextension_table" --autogenerate

Review Autogenerated Code

Always open and inspect the generated file under migration/<plugin_name>/versions/ before running it. Since multiple extensions and CKAN core share the same database, --autogenerate can sometimes falsely detect tables belonging to other extensions as "deleted" or "modified". Ensure the upgrade() and downgrade() blocks strictly target your own extension's tables and columns.

Note

If --autogenerate does not detects your model, most likely it happens because your model was never registered inside SQLAlchemy's registry. Try importing the model into plugin.py of the extension before running the command. Once migration is created, you can remove this unused import.

plugin.py
from .model import MyExtensionItem

class MyPlugin(...): ...

Running Migrations

You can manage and execute migrations using the ckan db CLI tool:

Check Pending Migrations

To see if there are any database migrations that have not yet been run on the current database instance:

ckan db pending-migrations

Run Migrations

To execute all pending migrations and bring your database schema up to the latest revision:

ckan db upgrade

To upgrade only the database migrations for a specific plugin:

ckan db upgrade -p myplugin

In test environments, migrations are automatically run during test setup via test fixtures.

Tip

You can also revert migrations. The basic command is:

ckan db downgrade -p PLUGIN

It reverts all migrations of the plugin.

When you have multiple migrations, you probably want to revert/apply only the last migration, polishing its code. To do it, add -v -1 argument to the command. The number after -v/--version option specifies number of migrations affected by the command. The number is negative, as we are moving backward. When working with db upgrade you can also specify the number of applied migrations, but there you'd use positive numbers.

ckan db downgrade -p PLUGIN -v -1