Skip to content

Migration Guide

velocity-migrate ships with self-hosted Velocity and applies schema changes to your Postgres. Interactive mode for humans, headless mode for Ansible.

When to run it

Run velocity-migrate after every Velocity update, before you start the main binary. The Velocity binary refuses to boot if its embedded schema version is ahead of your database — this is intentional, and prevents corrupted writes against an old schema.

  • After downloading a new Velocity release tarball — always.
  • After a fresh install, before first launch.
  • Never during a live session. Stop the Velocity binary first, run migrate, then start it again.

Status check

Before doing anything, ask the tool what it sees. The status subcommand is read-only and safe to run any time, including while Velocity is up.

velocity-migrate status
velocity-migrate status --json

Output lists the current schema version, the binary's target version, the count of pending migrations, and a hash of each pending file. The --json flavor is stable and intended for monitoring pipelines and CI gates.

Interactive run

The default mode is interactive. It prints every pending migration, asks you to confirm, takes a backup, applies migrations one at a time, and verifies the final schema.

velocity-migrate run --backup-first

You'll see one confirmation prompt up front (“Apply 3 migrations? [y/N]”) and a per-step progress line as each runs. On any failure, the tool stops, prints the offending SQL, and tells you exactly which pg_restore command to use.

Headless run for Ansible

For automated infrastructure, skip the prompt with --auto-confirm. Exit code is zero on success, non-zero on any failure (with the specific code documented in the man page, suitable for Ansible failed_when rules).

velocity-migrate run \
  --backup-first \
  --auto-confirm \
  --log-format json

We recommend gating the run on a successful velocity-migrate status --json first, then running the actual migrate, then starting the Velocity binary. That ordering keeps your playbook idempotent: no pending migrations means the run step is a no-op.

Backup recovery

--backup-first shells out to pg_dump with the connection string Velocity already has configured, and writes a custom-format dump to ./velocity-migrate-backups/ before touching the database. The file name embeds the timestamp and the source schema version.

To restore, use standard Postgres tooling — we don't wrap it:

pg_restore \
  --clean --if-exists \
  --dbname=postgres://velocity:***@localhost/velocity \
  ./velocity-migrate-backups/velocity-v42-2026-05-12T14-03-00Z.dump

Keep backups for at least as long as you keep the old Velocity binary. If you ever roll the binary back, you'll need the matching schema snapshot to roll the database back with it.

Reading the log file

Every run writes a structured log file alongside the backup:

./velocity-migrate-backups/
  velocity-v42-2026-05-12T14-03-00Z.dump
  velocity-v42-2026-05-12T14-03-00Z.log

The log captures: the connection string with the password redacted, the source and target schema versions, each migration filename and its SHA-256, the elapsed time per statement, and the verification query results. On failure, the final entries include the offending SQL and the Postgres error code.

If you open a support ticket about a failed migration, attaching this log file is usually enough for us to diagnose without needing access to your environment.

Question we didn't cover?

Email sales@aethernaut.ai — we keep docs honest and respond inside one business day.