Schema Migrations

Over time, the ORM models in your application may change. Migrations provide a way to modify the database tables according to the changes in your models, without writing raw SQL.

The migrations that were applied to the database are recorded in the infi_clickhouse_orm_migrations table, so migrating the database will only apply any missing migrations.

Writing Migrations

To write migrations, create a Python package. Then create a python file for the initial migration. The migration files must begin with a four-digit number, and will be applied in sequence. For example:

   +-- analytics_migrations

Each migration file is expected to contain a list of operations, for example:

from infi.clickhouse_orm import migrations
from analytics import models

operations = [

The following operations are supported:


A migration operation that creates a table for a given model class. If the table already exists, the operation does nothing.

In case the model class is a BufferModel, the operation first creates the underlying on-disk table, and then creates the buffer table.


A migration operation that drops the table of a given model class. If the table does not exist, the operation does nothing.


A migration operation that compares the table of a given model class to the model’s fields, and alters the table to match the model. The operation can:

  • add new columns
  • drop obsolete columns
  • modify column types

Default values are not altered by this operation.


A compound migration operation for altering a buffer table and its underlying on-disk table. The buffer table is dropped, the on-disk table is altered, and then the buffer table is re-created. This is the procedure recommended in the ClickHouse documentation for handling scenarios in which the underlying table needs to be modified.

Applying this migration operation to a regular table has the same effect as an AlterTable operation.


A migration operation that runs a Python function. The function receives the Database instance to operate on.

def forward(database):

operations = [


A migration operation that runs raw SQL queries. It expects a string containing an SQL query, or an array of SQL-query strings.


operations = [
    RunSQL('INSERT INTO `test_table` (field) VALUES (1)'),
      'INSERT INTO `test_table` (field) VALUES (2)',
      'INSERT INTO `test_table` (field) VALUES (3)'

Running Migrations

To migrate a database, create a Database instance and call its migrate method with the package name containing your migrations:


Note that you may have more than one migrations package.

<< Table Engines | Table of Contents | System Models >>