Edit your schema. pgmt handles the rest.

A schema-as-code tool for PostgreSQL with dependency tracking, instant apply, and production-ready migrations.

terminal
$ git diff schema/functions/calculate_score.sql
  CREATE OR REPLACE FUNCTION calculate_score(
-   user_id INTEGER
+   user_id INTEGER,
+   include_bonus BOOLEAN DEFAULT false
  )

$ pgmt apply

📋 8 changes

  ✓ Drop view public.executive_dashboard
  ✓ Drop view public.daily_stats
  ✓ Drop view public.user_rankings
  ✓ Update function public.calculate_score(integer)
  ✓ Create function public.calculate_score(integer, boolean)
  ✓ Create view public.user_rankings
  ✓ Create view public.daily_stats
  ✓ Create view public.executive_dashboard

✅ Applied 8 changes

Your schema files

schema/
├── functions/
│   └── calculate_score.sql  ← changed
└── views/
    ├── user_rankings.sql       ← depends
    ├── daily_stats.sql         ← depends
    └── executive_dashboard.sql ← depends

One function changed. pgmt detected 3 dependent views, dropped them in the right order, applied the update, and recreated everything — automatically.

No manual dependency tracking. No copy-paste errors. No broken deploys.

Your database, with hot reload

Run pgmt apply --watch and forget about it. Edit a schema file, save — your dev database updates instantly. No migration files during development, no manual dependency management.

terminal
$ pgmt apply --watch
👀 Watching schema/ for changes...

  schema/functions/calculate_score.sql changed

📋 8 changes
  ✓ Drop view public.executive_dashboard
    ...
  ✓ Create view public.executive_dashboard

✅ Applied 8 changes

Production-ready when you are

When you're done iterating, generate an explicit migration file. Review it, edit it, deploy it. Nothing touches production without you approving it.

Multi-section migrations handle the hard stuff: concurrent indexes, data backfills, different timeouts and transaction modes — all in one file, with per-section retries.

sql V001__add_verified_column.sql
-- pgmt:section name="add_column"
--   timeout="5s"
ALTER TABLE users
  ADD COLUMN verified BOOLEAN;

-- pgmt:section name="backfill"
--   mode="autocommit" timeout="30m"
UPDATE users SET verified = false
  WHERE verified IS NULL;

-- pgmt:section name="add_index"
--   mode="non-transactional"
--   retry_attempts="10"
CREATE INDEX CONCURRENTLY
  idx_users_verified ON users(verified);

Your team reviews intent, not mechanics

With traditional migrations, PRs show a wall of DROP and CREATE statements. With pgmt, your schema files are code — the diff shows what actually changed.

sql Traditional migration PR
-- migrations/V042__update_score.sql
DROP VIEW executive_dashboard;
DROP VIEW daily_stats;
DROP VIEW user_rankings;
DROP FUNCTION calculate_score(integer);
CREATE FUNCTION calculate_score(
  user_id INTEGER,
  include_bonus BOOLEAN DEFAULT false
) RETURNS INTEGER AS $$ ... $$;
CREATE VIEW user_rankings AS ...
CREATE VIEW daily_stats AS ...
CREATE VIEW executive_dashboard AS ...
diff pgmt schema PR
-- schema/functions/calculate_score.sql CREATE OR REPLACE FUNCTION calculate_score( user_id INTEGER, + include_bonus BOOLEAN DEFAULT false ) RETURNS INTEGER AS $$ ... $$ LANGUAGE plpgsql;

Drift Detection

Detect unauthorized production changes with CI-ready JSON output

Easy Rebase

Branch behind? Regenerate your migration with one command

Full PostgreSQL

Triggers, RLS, grants, custom types, extensions — not just tables

Any Framework

Works alongside Rails, Django, Go, Node — pgmt manages the schema, your app reads it

Ready to try it?

Get started in minutes.

bash Install pgmt
curl -fsSL https://pgmt.dev/install.sh | sh