Skip to main content
supaschema integrates directly into a standard Supabase project layout. This guide walks you through installing the package, writing a declarative schema file, generating a migration, and validating it — all without touching a running database. You’ll be ready to push your first supaschema-generated migration in under five minutes.
1

Install supaschema

supaschema requires Node.js 22 or later and targets PostgreSQL 15 or later. Install it as a dev dependency in your project:
npm install --save-dev supaschema
After installation, a postinstall script runs automatically and scaffolds a supaschema.config.json file in your project root if one does not already exist. You can also create or regenerate this file at any time by running npx supaschema init.
Verify the installation:
npx supaschema --version
2

Write your declarative schema

supaschema reads schema files from the path(s) configured in supaschema.config.json. By default it looks in supabase/schemas/. Create your first schema file:
mkdir -p supabase/schemas
Then create supabase/schemas/001_app.sql with the following content:
-- supabase/schemas/001_app.sql

CREATE SCHEMA app;

CREATE TABLE app.accounts (
  id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL
);

ALTER TABLE app.accounts ENABLE ROW LEVEL SECURITY;

CREATE POLICY accounts_select ON app.accounts
  FOR SELECT
  TO public
  USING (true);
You can split your schema across as many files as you like. supaschema processes all .sql files in your configured schemaPaths in lexicographic order. Prefix filenames with a numeric sequence (e.g. 001_, 002_) to control load order explicitly.
Your schema files are the single source of truth. You edit them directly — you never write migration SQL by hand.
3

Generate a migration with diff

With your schema file in place, run diff to generate a migration:
npx supaschema diff
supaschema compares your declarative schema files (--to, defaulting to supabase/schemas) against the current applied database state (--from, defaulting to your configured database, then falling back to git:HEAD) and writes a new timestamped migration file to supabase/migrations.You will see output similar to:
✔ Parsed schema tree (3 objects)
✔ Resolved migrations history (0 migrations)
✔ Computed diff (4 operations)

Created: supabase/migrations/20240101120000_migration.sql
The generated migration file contains only the SQL needed to move from your current state to your desired state. Every statement is guarded so the migration is safe to re-run. Open it to review the output:
-- supabase/migrations/20240101120000_migration.sql
-- Generated by supaschema 0.1.0.
-- Operations: 1 create schema, 1 create table, 1 enable rls, 1 create policy
-- supaschema: lineage from=0000000000000000... to=4db806bc9b786ea2...
SET lock_timeout = '5s';

CREATE SCHEMA IF NOT EXISTS app;

CREATE TABLE IF NOT EXISTS app.accounts (
    id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    name text NOT NULL
);

DO $supaschema$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_constraint c
                 JOIN pg_catalog.pg_class t ON t.oid = c.conrelid
                 WHERE t.relname = 'accounts' AND c.conname = 'accounts_pkey') THEN
    ALTER TABLE app.accounts ADD CONSTRAINT accounts_pkey PRIMARY KEY (id);
  END IF;
END
$supaschema$;

ALTER TABLE app.accounts ENABLE ROW LEVEL SECURITY;

CREATE POLICY accounts_select ON app.accounts
    FOR SELECT
    TO public
    USING (true);
Pass --from and --to explicitly to override defaults. Sources use prefixes to declare their type:
# Diff against a specific git commit instead of the live database
npx supaschema diff --from git:HEAD --to dir:supabase/schemas

# Diff against a specific database URL
npx supaschema diff --from database:$DATABASE_URL --to dir:supabase/schemas
4

Validate the migration with check

Before applying the migration, use check to validate it:
npx supaschema check supabase/migrations/20240101120000_migration.sql
check parses the migration using the PostgreSQL WASM parser and verifies its structural correctness and safety. A passing check looks like:
✔ Parsed 4 statements
✔ No destructive operations detected
✔ Migration is replay-safe

supabase/migrations/20240101120000_migration.sql — OK
If check reports any issues, review the flagged statements before applying the migration. supaschema will never silently suppress warnings that could result in data loss.
5

Apply the migration with Supabase CLI

supaschema generates migrations but never applies them to a database directly. Use the Supabase CLI to push your migration as you normally would:
supabase db push
This keeps your existing deployment workflow intact. supaschema slots in as the migration generation step; the Supabase CLI handles the application step.
supaschema never modifies your database, reads from a live connection during diff, or requires a shadow database at any point. Migration generation is entirely offline.
6

(Optional) Generate TypeScript types

Once your schema is defined, you can generate TypeScript types from it:
npx supaschema types
This produces a type file derived from your declarative schema, giving you end-to-end type safety from database schema to application code — no separate supabase gen types step required against a live database.
✔ Parsed schema tree (3 objects)
✔ Generated TypeScript types

database.types.ts
database.zod.ts

What’s Next?

You’ve installed supaschema, written a declarative schema, generated and validated a migration, and seen how to push it. From here you can:

Installation & Configuration

Explore all configuration options, shell completions, and the doctor command.

Commands Reference

Deep-dive into diff, check, verify, and all other supaschema commands.

Type Generation

Learn how to configure and customise TypeScript type output.

CI/CD Integration

Add supaschema to your GitHub Actions or other CI pipeline.