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
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 projectcreate 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:
stitchdb migration list # linked project
stitchdb migration list --local # local database| Status | Meaning |
|---|---|
applied | The database has it |
pending | Only in your files: db push will apply it |
changed locally | Applied, 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 database | Applied 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):
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 differencesdb 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:
# 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 upWhen 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
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
stitchdb db dump -f schema.sql # schema of your own schemas
stitchdb db dump --data-only -f data.sql
stitchdb db dump --localDumps include your schemas (public and any you created), never the platform's (auth, storage, ...). Data dumps need the owner or admin role.