On this page

Migrations

Keep your schema in SQL migration files, test them locally and push them to your project with stitchdb db push.

A migration is a SQL file in stitchdb/migrations/, named <version>_<name>.sql where the version is a UTC timestamp. Migrations run once, in version order, each in its own transaction: if one fails, nothing from it is applied and the run stops.

#Create and apply

Terminal
stitchdb migration new create_todos
# write the SQL in stitchdb/migrations/<version>_create_todos.sql
stitchdb migration up        # apply to the local database
stitchdb db push             # apply to the linked project
SQL
create table public.todos (
  id bigint generated always as identity primary key,
  title text not null,
  done boolean not null default false
);
alter table public.todos enable row level security;

stitchdb db push lists the migrations the project doesn't have and asks before applying them (--yes to skip the question, --dry-run to only list). Migrations run as your project's own database role, like the SQL Editor.

Before asking, it warns about statements that would lock a busy table and shows a safer version (Safe schema changes).

#History

Each project records applied migrations in stitchdb_migrations.schema_migrations (version, name, a SHA-256 checksum of the SQL, when and by whom). See it in Studio under Database → Migrations, or compare with your files:

Terminal
stitchdb migration list          # linked project
stitchdb migration list --local  # local database
StatusMeaning
appliedThe database has it
pendingOnly in your files: db push will apply it
changed locallyApplied, but the file was edited afterwards. Applied migrations must not change: restore the file and put the change in a new migration.
only on the databaseApplied from somewhere else (another developer, Studio, a branch merge): run stitchdb db pull

#Changes made outside migrations

Tables created in Studio or with the SQL Editor are not in your files. Two commands bring them in (they build a temporary database from your migrations in about a second and compare):

Terminal
stitchdb db diff                     # local database vs your migrations
stitchdb db diff --linked -f my_changes  # linked project vs your migrations, saved as a new migration
stitchdb db pull                     # fetch missing migrations + capture remaining differences

db pull records what it writes as applied on the project, so db push won't run it there again. On a project that has no migrations yet, db pull writes its whole current schema as your first migration. Review generated SQL before committing it: the diff covers tables, columns, functions, views, policies, indexes, triggers, constraints and extensions; anything unusual is left as a comment to review.

#Declarative schemas

Instead of writing each change by hand, you can keep the schema you want in stitchdb/schemas/*.sql (or the files listed in [db] schema_paths) and let the CLI write the migration:

Terminal
# edit stitchdb/schemas/todos.sql: add a column, a policy, an index…
stitchdb db diff -f add_priority   # migration from your migrations to your schema files
stitchdb migration up

When schema files exist, db diff compares with them; --local compares with the local database instead, and --linked with the linked project.

#Studio

In the SQL Editor, Run → Save as migration either runs the SQL as a migration or, when you already ran it, only records it in the history. Database → Migrations shows every applied migration with its SQL.

#Fixing the history

Terminal
stitchdb migration repair 20261019120000 --status applied   # mark as applied without running
stitchdb migration repair 20261019120000 --status reverted  # forget it (does not undo the SQL)

#Dumps

Terminal
stitchdb db dump -f schema.sql          # schema of your own schemas
stitchdb db dump --data-only -f data.sql
stitchdb db dump --local

Dumps include your schemas (public and any you created), never the platform's (auth, storage, ...). Data dumps need the owner or admin role.