verify command gives you a cryptographic proof that your migration is both idempotent and convergent. It creates two throwaway databases, applies the migration twice to the first, applies your target schema model directly to the second, then compares catalog fingerprints across both. If the fingerprints match, your migration is proven safe. If they diverge, supaschema tells you exactly which catalog objects differ. Temp databases are always cleaned up on success — you only retain them on failure when you need to inspect what went wrong.
verify requires a local database URL for a PostgreSQL instance where your user has CREATEDB privileges. It refuses remote databases by default to protect production data from accidental writes.How It Works
- Idempotency — applying the migration a second time produces no change.
- Convergence — the migration drives the database to exactly the schema your declarative model describes.
Examples
Flags
The before-state source. supaschema applies this state to both temp databases before applying any migration or model SQL. Accepts a database URL,
git:<ref>, or dir:<path>. This should match the --from value you used when generating the migration with diff.The after-state (target model) source. Applied directly to the second temp database for the convergence comparison. Accepts the same specifiers as
--from. Typically dir:supabase/schemas.Path to the
.sql migration file you want to verify. This file is applied twice to the first temp database (once for functionality, once to prove idempotency). Defaults to the newest .sql file in your configured migrations directory.Overrides the directory used when resolving the default
--migration file. Defaults to supabase/migrations.Connection string for a local PostgreSQL instance where your user has
CREATEDB privileges. supaschema creates and destroys temp databases on this server. You can also set the SUPASCHEMA_DATABASE_URL environment variable instead of passing this flag on every invocation.Pre-creates any
NOLOGIN roles that the migration grants permissions to (for example authenticated, anon, service_role in Supabase projects) before applying migration SQL. Without this flag, GRANT ... TO authenticated will fail in a fresh temp database that does not have those roles.Stubs out Supabase-specific surfaces (extensions, helper functions, storage schema, etc.) in both temp databases so that migrations that reference Supabase internals apply cleanly. Enabled automatically when the
supabase-auto adapter is active. Pass explicitly if you are using a generic adapter but targeting a Supabase-hosted database.Preserves both temp databases after a failure instead of dropping them. Use this flag when you need to inspect the diverging catalog state with
psql or a GUI client. Databases are always dropped on success regardless of this flag.Path to a supaschema config file. Defaults to
supaschema.config.ts (or .js / .json) in the current working directory.Environment Variables
| Variable | Description |
|---|---|
SUPASCHEMA_DATABASE_URL | Default database URL — equivalent to --database-url |
SUPASCHEMA_VERIFY_ALLOW_REMOTE | Set to 1 to allow verify against remote databases. Only use this for intentionally disposable remote infrastructure. |
Diagnostic Codes
Whenverify fails, it emits one or more of the following structured diagnostic codes:
| Code | Meaning |
|---|---|
SUPA_VERIFY_FINGERPRINT_MISMATCH | The catalog fingerprints of the migration database and the target model database do not match. The migration does not converge to the declared schema. |
SUPA_VERIFY_RECONVERGENCE | The second application of the migration changed the catalog state, proving the migration is not idempotent. |
SUPA_VERIFY_FAILED | A general failure during database setup, SQL application, or fingerprint collection. Check the accompanying error message for details. |
SUPA_VERIFY_CLEANUP_FAILED | The temp databases could not be dropped after a failure. The connection string and database names are printed so you can clean them up manually. |
Exit Codes
| Code | Meaning |
|---|---|
0 | Both fingerprints match and the migration is proven idempotent and convergent |
2 | Verification failed — diagnostics contain one or more of the codes above |
CI Integration
Runverify as a required check on every pull request that touches supabase/migrations:
Inspecting Failures
Whenverify returns SUPA_VERIFY_FINGERPRINT_MISMATCH or SUPA_VERIFY_RECONVERGENCE, re-run with --keep-databases and connect to each temp database to compare them directly:
\dt *.* or query information_schema.tables in each database to locate the diverging objects reported in the diagnostic output.