Migrations and types
Applying and recording schema changes as versioned SQL, downloading the schema as SQL, and making TypeScript types for supabase-js.
Migrations and types
Keep the SQL that changes your schema as versioned files, and you can apply the same changes to another project (staging, then production)
in the same order. Changes made with run_sql leave no record.
list_migrations version, name and time of each applied migration (oldest first)
apply_migrations runs only the ones not yet applied, in version order, and records them
remove_migration_record removes one record (what it made stays)
dump_schema the current schema as SQL that builds it again
generate_typescript_types the Database type for supabase-jsHow they are applied
- One migration is one transaction. If it fails, that migration alone is rolled back whole and applying stops.
- Versions are numbers (usually
YYYYMMDDHHMMSS) and run in numeric order. Versions already recorded are skipped. - A new version earlier than the last applied one is refused. For a branch merged late, use
include_all: true. - A file whose content changed after it was recorded is not run again; it is reported as
drifted. To fix something, write a new migration. - It runs with the same rights as
run_sql(a write token; owners, admins and developers), as the project's service_role. - The data schema is first on the search_path, so a bare name such as
create table notes (...)is enough.
Where the record is kept
In the project's oneend_migrations table. The owner can read it with SQL; it has RLS on and no rules, so the publishable key cannot see it.
It plays the same part as supabase_migrations.schema_migrations.
The schema as a file, the types as code
dump_schema gives types, sequences, tables and constraints, foreign keys, indexes, functions, views, triggers, RLS and rules as SQL.
When you start managing an existing project with migrations, save this as the first migration
and record it only, with record_only: true in apply_migrations. Running it would clash with the tables that already exist.
generate_typescript_types gives the same shape as supabase gen types typescript (Row/Insert/Update/Relationships under Tables,
Views, Args/Returns under Functions, Enums, CompositeTypes). The schema name is public.
The same over HTTP
GET /projects/<ref>/migrations
POST /projects/<ref>/migrations {migrations: [{version, name, sql}], include_all, record_only, dry_run}
DELETE /projects/<ref>/migrations/<version>
GET /projects/<ref>/schema {sql, objects}
GET /projects/<ref>/types/typescript?schema=public {types}