Kumo.io

Docs Self-hosting & operations

Self-hosting & operations

Database migrations

Every Kumo.io release brings its database schema with it. Migrations only move forward, are checksummed, and take a lock, so they are safe to run on every start — or as a separate release step if you prefer.

Applies to: Self-hostedPlan: Allforward-onlychecksummedadvisory-locked

When migrations run

You rarely run migrations by hand:

Installation When the schema is migrated
Single containerOn every start, before Kumo.io serves anything
kumo deployment on Docker ComposeBy kumo deployment apply, in a one-time bootstrap step before the containers start
AWS stackBy a one-shot migrate task inside your VPC, on every kumo deployment apply

The API, worker and scheduler roles also migrate on start by default. Running migrations again when nothing is pending does nothing.

What makes them safe

  • Forward-only. There are no down migrations. To undo a release, restore the backup you took before upgrading and start the previous version — see Backups and restore.
  • Checksummed. Kumo.io records a SHA-256 of every migration it applies. If an applied migration's file has changed, Kumo.io stops and reports it as drifted instead of letting your schema silently diverge.
  • Locked. A whole migration run holds a PostgreSQL advisory lock, so two processes starting at once take turns instead of racing.
  • One transaction per migration. A migration that fails rolls back and is not recorded, so you can fix the cause and run it again.

Check the schema without changing it

kumo db migrate --validate

It reports what is applied, pending and drifted, and changes nothing:

  • Schema up to date — N applied, 0 pending, 0 drifted. — exit code 0.
  • Schema NOT up to date — N pending, M drifted. — exit code 1, with one pending or DRIFTED line per migration.

On the single container, run it with docker exec kumo kumo db migrate --validate.

Run migrations yourself

kumo db migrate

It applies everything pending and prints Migrations OK — applied N new migration(s). with one applied line each, then exits 0. If drift blocks the run, it prints Migrations FAILED — … with the drifted versions and exits 1.

kumo db migrate reads the database connection from KUMO_PG_DSN, or from --dsn.

Migrate as a separate release step

If you'd rather migrate once per release than on every start — for example with several API containers — run kumo db migrate as a one-off step, then start each server role with --no-auto-migrate:

kumo db migrate
kumo serve tenant-api --no-auto-migrate
kumo serve worker --no-auto-migrate
kumo serve scheduler --no-auto-migrate

The exit codes are made for release scripts: stop the rollout if kumo db migrate exits non-zero.

An older version against a newer schema

If a running Kumo.io finds migrations in the database that it doesn't know about — an older container still running during an upgrade, or after a rollback — it logs a warning that the database may be newer than the code, and keeps running. Kumo.io's schema changes are designed to be additive first, so that a schema one release ahead stays compatible with the release before it.

The built-in database's PostgreSQL version

The single container's built-in database is PostgreSQL 17. If its data on the /data volume was created by a different PostgreSQL major version, the container refuses to start and says so, rather than risk the data.

See your own cloud in Kumo.io. Read-only access. Nothing in your account changes.

Free Trial