# Supabase pg-delta migration guide: adopt declarative schemas safely

> Move an existing Supabase project to pg-delta with a baseline, reviewed SQL, strict coverage checks, and a staged rollout.
> By Dave · 2026-10-14
> Source: https://otf-kit.dev/blog/supabase-pg-delta-declarative-schema

A schema diff can be technically valid and still remove data you meant to keep. That is why switching an existing Supabase project to Declarative Schemas 2.0 needs a review plan, not a blind toggle.

The Supabase CLI now uses pg-delta for this workflow. It can detect schema changes that the previous migra-based diff missed, including changes to RLS policies, grants, comments, domains, and view settings. That broader coverage is useful, but it also makes the generated migration worth reading carefully: pg-delta prefers representing the schema accurately over guessing that a destructive-looking change was intended to preserve data.

If you already use declarative schemas, you can test the new engine on a branch and compare its first generated migration before applying anything. If your project uses hand-written migrations, that workflow does not need to change. This guide is for teams choosing to move an existing project to the new diff engine.

![Byte lifts a structural blueprint from a database vessel and aligns editable schema sheets beside a separate branching migration-history track.](https://cdn.otf-kit.dev/blog/supabase-pg-delta-declarative-schema/inbody1-20261014a.webp)

*Establish the database baseline, keep the desired schema editable, and compare it with the applied migration history.*

## Know which files are the source of truth

Supabase declarative schemas keep SQL definitions in `supabase/schemas/`. The CLI compares those files with migration history and writes a new SQL migration. The schema files are the desired definition; the migration history records changes that have been applied.

That distinction matters when you start from a project that already has a live database. If the project has no schema files yet, you can export its current database structure with:

```bash
supabase db schema declarative generate --linked
```

Before generating, confirm that the CLI is linked to the intended project and that its migration history is current. Supabase says that a project without migration history should run `supabase db pull` once to establish a baseline. A declarative pull refreshes the schema files; it does not, by itself, record a change that is already live as an applied migration. If a dashboard or SQL-editor change is already present in production, record it in migration history first. Otherwise a later push can try to create an object that already exists.

If the repository already has declarative schema files generated with migra, the first pull with pg-delta can produce a catch-up migration. Treat that as a review event. Do not apply the output just because the command completed successfully.

## Enable pg-delta on an existing project

The Supabase announcement documents pg-delta for Supabase CLI 2.119 and later. Add this block to the project's `supabase/config.toml`:

```toml
[experimental.pgdelta]
enabled = true
```

New CLI projects get Declarative Schemas 2.0 by default. Existing projects remain on migra until they opt in. Keep the change in a dedicated branch so the diff engine, schema files, and generated migration can be reviewed together.

If your team depends on migra while evaluating the switch, the CLI configuration can keep it enabled with pg-delta disabled. Avoid mixing the engine switch with unrelated schema changes: one focused pull request makes it easier to identify whether a changed statement came from the new diff behavior or from application work.

## Generate a migration without applying it

Once the schema files represent the intended state, ask the CLI to generate the migration but leave it unapplied:

```bash
supabase db schema declarative sync -f pg_delta_baseline --no-apply
```

This writes a plain SQL file under `supabase/migrations/`. Read it as a database change, not as generated scaffolding. Start with the operations that can remove or rewrite data:

- Does a dropped column have a replacement, and has the application stopped reading it?
- Does a table or policy change widen access, narrow access, or change which role can act?
- Does a view preserve its intended owner, grants, and `security_invoker` behavior?
- Are extension-managed objects changed through their extension's API?
- Did the tool flag unsupported objects or destructive statements?

A renamed column is a useful example. The engine may represent it as a drop followed by an add because it cannot know that the two names refer to the same data. Applying that SQL unchanged can lose the old column's values. Rewrite the migration to use a safe rename or a staged expand-and-contract change, then review the result again.

The same caution applies to policies and grants. More complete coverage can surface access changes that were missing from earlier diffs. Check the generated SQL against the intended access model and test it with the roles your app actually uses. A green command exit is not evidence that the resulting permissions are right.

## Make unsupported objects fail the build

During the first migration, warnings deserve attention. Supabase documents `--strict-coverage` as a way to make unsupported objects fail the command, which is a better default for CI than silently accepting an incomplete diff.

Use a staged adoption:

1. Generate the migration locally with `--no-apply`.
2. Review the SQL in a pull request with someone who understands the production schema.
3. Run the migration against a disposable or staging database restored from representative structure and data.
4. Exercise key application paths, including RLS-protected reads and writes.
5. Require strict coverage in CI, and keep the generated migration as a versioned artifact.
6. Apply to production only through your established migration process, with a rollback and recovery plan.

The point is not to make every migration reversible by magic. It is to make the diff visible early enough that a developer can correct a destructive operation before it reaches production.

## Keep the alpha and scope limits in view

Supabase describes pg-delta as alpha, so breaking changes may land between releases. Pin the CLI version used in local work and CI, then re-run the same representative schema cases when you upgrade. Keep a known-good migration output in review so version changes are easy to spot.

The tool generates schema changes; it does not orchestrate a zero-downtime rollout or create a TypeScript schema DSL. Supabase lists support for PostgreSQL 14 through 18, not PostgreSQL 13 or earlier. Storage bucket rows are outside the declarative diff today, even though policies on `storage.objects` are part of the schema. Do not assume that moving your database structure to schema files has captured every setting managed through the dashboard.

If you use extensions such as pgmq or pg_partman, inspect their generated operations too. The engine is designed to call extension APIs for extension-owned objects instead of dropping and recreating their underlying tables. It can also flag destructive extension operations. Keep the extension's own behavior in the migration review.

![Dex pauses a red destructive-looking schema change before it reaches the staging database while Luna records the review and safer staged path.](https://cdn.otf-kit.dev/blog/supabase-pg-delta-declarative-schema/inbody2-20261014a.webp)

*Review the generated migration, correct destructive changes, and rehearse the result in staging before production rollout.*

## Choose a safe first cut

A migration-engine change is easiest to evaluate when the first cut is narrow: one representative project, one reviewable migration, and a staging pass before production. Start with the objects your application depends on most, especially RLS policies, grants, views, and extension-managed structures. If the output is surprising, stop and investigate before widening the rollout.

For general rollout discipline, see our [Supabase migration safety guide](/blog/supabase-migrations-zero-downtime-mobile). It covers reversible changes and staged deployment practices; this pg-delta adoption adds a separate prerequisite: validate that the new diff engine sees the objects you intend it to manage.

If you want an editable account and dashboard shell around an internal schema-review workflow, OTF's [SaaS Dashboard kit](/templates/saas-dashboard) is an optional starting point. It is a Vite and Hono starter with a PostgreSQL database, sign-in, projects, teams, and dashboard UI. It does not include Supabase, pg-delta, or a database migration integration.

## Sources

- [Declarative Schemas 2.0 with pg-delta](https://supabase.com/blog/declarative-schemas-2-0-pg-delta) — Supabase's 13 October 2026 announcement; checked 14 October 2026.

