Quick Start
By the end of this guide, you’ll change one file and watch pgmt automatically cascade changes through your entire dependency graph. Takes about 10 minutes.
Install pgmt
Section titled “Install pgmt”curl -fsSL https://pgmt.dev/install.sh | shOther methods (npm, cargo) and prerequisites are on the installation page. You’ll need Docker running — pgmt uses it for the shadow database.
Setup Database
Section titled “Setup Database”pgmt requires PostgreSQL 13 or later. Choose your preferred option:
Docker (Recommended):
docker run -d \ --name pgmt-dev \ -e POSTGRES_PASSWORD=dev \ -e POSTGRES_DB=myapp_dev \ -p 5432:5432 \ postgres:18Already have PostgreSQL? Just create a database:
createdb myapp_devInitialize Project
Section titled “Initialize Project”# Create project directorymkdir my-app && cd my-app
# Initialize pgmt (Docker users)pgmt init --dev-url postgres://postgres:dev@localhost/myapp_dev --defaults
# For local PostgreSQL without password# pgmt init --dev-url postgres://localhost/myapp_dev --defaultsThis creates:
my-app/├── schema/ # Your SQL schema files├── migrations/ # Generated migration files├── schema_baselines/ # Baseline snapshots (created on-demand)└── pgmt.yaml # ConfigurationWant more control? Run pgmt init without --defaults for an interactive setup that:
- Detects your PostgreSQL version and installed extensions, and warns when the stock shadow image won’t work (e.g. PostGIS) with a prompt for a custom image
- Detects schemas your shadow image provides (PostGIS’s
topology, Supabase’sauth, …) and offers to exclude them from management - Shows you exactly what’s in your database (if importing existing schema)
- Lets you choose what the generated schema files include (grants, triggers, …)
- Automatically validates generated schema files and explains dependency issues
Create Your First Schema
Section titled “Create Your First Schema”Create a simple table:
cat > schema/users.sql << 'EOF'CREATE TABLE users ( id SERIAL PRIMARY KEY, email TEXT NOT NULL, full_name TEXT NOT NULL, created_at TIMESTAMP DEFAULT NOW());EOFNow add a view that depends on it:
cat > schema/active_users.sql << 'EOF'-- require: users.sqlCREATE VIEW active_users ASSELECT * FROM users;EOFNotice the -- require: users.sql? This is like import in Python or require in Node.js - it declares dependencies and lets you organize your schema however makes sense for your project.
Apply the schema to your dev database:
pgmt applypgmt will:
- Create a shadow database
- Load your schema files in dependency order
- Compare with your dev database
- Apply the necessary changes
Automatic Dependency Tracking
Section titled “Automatic Dependency Tracking”Here’s what makes pgmt special. Let’s add a column to the base table:
cat > schema/users.sql << 'EOF'CREATE TABLE users ( id SERIAL PRIMARY KEY, email TEXT NOT NULL, full_name TEXT NOT NULL, is_active BOOLEAN NOT NULL DEFAULT true, -- New column created_at TIMESTAMP DEFAULT NOW());EOFNow apply the change:
pgmt applyWhat just happened?
pgmt automatically:
- Dropped the
active_usersview (its column list is about to change) - Added the column:
ALTER TABLE users ADD COLUMN is_active boolean DEFAULT true NOT NULL - Recreated the
active_usersview, which now includesis_active
The view file didn’t change - it still says SELECT * FROM users - but pgmt knows it needs to be recreated because the underlying table structure changed.
What About Renames?
Section titled “What About Renames?”If you rename full_name to name in the schema file, pgmt sees a column
named full_name that disappeared and a column named name that appeared.
From the schema files alone there’s no way to tell a rename apart from a
genuine drop-and-add, and guessing wrong in either direction loses data - so
pgmt refuses to guess. It proposes the drop and flags it as a destructive
operation for you to review.
To actually rename a column:
- In development: run the rename yourself against the dev database
(
psql -c 'ALTER TABLE users RENAME COLUMN full_name TO name'), then update the schema file to match. The nextpgmt applysees no difference. - For production: run
pgmt migrate newand edit the generated migration, replacing theDROP COLUMN/ADD COLUMNpair with a singleRENAME COLUMNstatement.pgmt migrate validatereplays the edited migration against a shadow database and confirms your rename produces the declared schema.
This review-don’t-guess approach is a core design decision - see the philosophy page for the reasoning.
Make It More Complex
Section titled “Make It More Complex”Let’s add another view that depends on the first one:
cat > schema/recent_users.sql << 'EOF'-- require: active_users.sqlCREATE VIEW recent_users ASSELECT * FROM active_usersWHERE created_at > NOW() - INTERVAL '7 days';EOFApply it:
pgmt applyNow update the active_users view definition to add a filter:
cat > schema/active_users.sql << 'EOF'-- require: users.sqlCREATE VIEW active_users ASSELECT * FROM users WHERE email IS NOT NULL; -- Added filterEOFApply again:
pgmt applypgmt automatically:
- Dropped
recent_users(depends on active_users) - Dropped
active_users(the view we’re changing) - Created
active_users(new definition with filter) - Created
recent_users(unchanged, but depends on active_users)
All in the correct order, based on the dependency graph.
Why This Matters
Section titled “Why This Matters”With traditional migration tools, you’d manually write:
-- Hope you remember all the dependencies!DROP VIEW recent_users;DROP VIEW active_users;CREATE VIEW active_users AS ...; -- Better get the order rightCREATE VIEW recent_users AS ...;With pgmt, you edit views and functions like source code. pgmt handles the drop/recreate mechanics, figures out the dependency cascade, and applies changes in the correct order. No manual migration scripts needed.
Schema Organization
Section titled “Schema Organization”The -- require: statements aren’t just for dependency resolution - they’re for organizing your schema like a real programming language:
schema/├── 01_foundation/│ └── extensions.sql # PostgreSQL extensions├── 02_core/│ ├── users.sql # Core entities│ └── posts.sql # require: users.sql└── 03_features/ └── analytics.sql # require: users.sql, posts.sqlOrganize by domain, by feature, by team ownership - whatever makes sense for YOUR project. pgmt handles the dependency graph automatically.
Generate Production Migration
Section titled “Generate Production Migration”When you’re ready to deploy to production, generate an explicit migration:
pgmt migrate new "initial schema with user views"This creates a migration file like:
migrations/1734567890_initial_schema_with_user_views.sqlReview the generated SQL:
cat migrations/*_initial_schema_with_user_views.sqlYou’ll see explicit SQL statements that you can review, test, and version control before deploying to production.
Pro Tips
Section titled “Pro Tips”Watch Mode for Active Development
Section titled “Watch Mode for Active Development”pgmt apply --watchAutomatically applies safe changes as you edit schema files. Prompts for confirmation on destructive operations (like dropping columns).
Preview Changes Before Applying
Section titled “Preview Changes Before Applying”pgmt apply --dry-runSee what would change without actually applying it.
Check Migration Status
Section titled “Check Migration Status”pgmt migrate statusSee which migrations have been applied to your database.
Using pgmt with AI Coding Agents
Section titled “Using pgmt with AI Coding Agents”If you use Claude Code or another agent compatible with the skills.sh ecosystem, install the pgmt skill so the agent knows how to edit schema files and generate migrations correctly instead of hand-writing migration SQL:
npx skills add gdpotter/pgmtNext Steps
Section titled “Next Steps”Learn the Workflow
Section titled “Learn the Workflow”Organize your schema:
- Schema Organization Guide - Multi-file patterns,
-- require:best practices
Work with a team:
- CI/CD Integration - Automated migrations, CI pipelines, deployment strategies
Handle complex changes:
- Migration Workflow - Creating, editing, and deploying migrations
Have an Existing Database?
Section titled “Have an Existing Database?”- Adopt Existing Database - Import existing schema, create baselines, team onboarding
Reference & Support
Section titled “Reference & Support”- CLI Reference - All commands and options
- Configuration Guide - Customize pgmt for your environment
- PostgreSQL Features - Complete list of supported database objects
- Troubleshooting - Common issues and solutions