pgmi runs your PostgreSQL deployments—but you control the transactions, order, and logic.
Unlike migration frameworks that decide when to commit and what to run, pgmi loads your files into PostgreSQL temp tables and runs your deploy.sql—a script you write in SQL that controls everything.
-- deploy.sql
-- pg_temp is PostgreSQL's session-scoped schema; your files exist only
-- for this session and are automatically dropped when it ends.
BEGIN;
DO $$
DECLARE
v_file RECORD;
BEGIN
FOR v_file IN (
SELECT path, content FROM pg_temp.pgmi_source_view
WHERE is_sql_file
ORDER BY path
)
LOOP
RAISE NOTICE 'Executing: %', v_file.path;
EXECUTE v_file.content;
END LOOP;
END $$;
COMMIT;pgmi deploy ./myapp --database mydbYour files are in a temp table. You query them with SQL. You decide what to execute. That's the entire model.
The Quick example above shows the core pattern: query files, execute with EXECUTE. The scaffolded templates use pgmi_plan_view (which adds metadata-driven ordering) instead of pgmi_source_view (raw access). See Session API for when to use each.
Go (all platforms):
go install github.com/vvka-141/pgmi/cmd/pgmi@latestHomebrew (macOS/Linux):
brew install vvka-141/pgmi/pgmiDebian/Ubuntu:
curl -1sLf 'https://dl.cloudsmith.io/public/vvka-141/pgmi/setup.deb.sh' | sudo bash
sudo apt update && sudo apt install pgmiWindows: Download from GitHub Releases or use go install above.
The fastest path to your first deployment:
pgmi init myapp --template basic
cd myapp
pgmi deploy . --database mydb --overwrite --forceThis creates a project with deploy.sql, runs it against a fresh database, and executes the SQL files in migrations/.
See the Getting Started Guide for a complete walkthrough.
pgmi is a good fit when you need:
- Conditional deployment logic — different behavior per environment, feature flags, custom phases
- Explicit transaction control — you decide where
BEGINandCOMMITgo - Full PostgreSQL power — use PL/pgSQL, query system catalogs, leverage
pg_advisory_lock
pgmi handles simple linear migrations out of the box — the basic template does exactly this. Its additional power is there when you need it.
See Why pgmi? for a detailed comparison with other tools.
| Guide | Description |
|---|---|
| Getting Started | Your first deployment in 10 minutes |
| Why pgmi? | When pgmi's approach makes sense |
| Coming from Flyway/Liquibase | Migration guides |
| CLI Reference | All commands, flags, exit codes |
| Configuration | pgmi.yaml reference |
| Session API | Temp tables and helper functions |
| Testing | Database tests with automatic rollback |
| Metadata | Optional script tracking and ordering |
| Security | Secrets and CI/CD patterns |
| Production Guide | Performance, rollback, monitoring |
| MCP Integration | Model Context Protocol for AI assistants |
pgmi ships with ready-to-use project templates:
pgmi templates list # See available templates
pgmi templates describe basic # See what a template includes
pgmi init myapp --template basic # Create a project| Template | Purpose |
|---|---|
basic |
Learning and simple projects. Linear migrations, minimal structure. |
advanced |
Production. Multi-schema, role hierarchy, MCP integration, metadata-driven. |
pgmi embeds AI-digestible documentation directly in the binary. AI coding assistants (Claude Code, GitHub Copilot, Gemini CLI) can discover and learn pgmi patterns:
pgmi ai # Overview for AI assistants
pgmi ai skills # List embedded skills
pgmi ai skill pgmi-sql # Load SQL conventionsWhen you tell an AI assistant "use pgmi for this project", it can query these commands to understand pgmi's philosophy, conventions, and best practices.
Store connection defaults in pgmi.yaml:
connection:
host: localhost
database: myapp
params:
env: developmentThen deploy with no flags:
pgmi deploy .Override per-environment:
pgmi deploy . -d staging_db --param env=stagingTests live in __test__/ or __tests__/ directories. Use the CALL pgmi_test() macro in your deploy.sql to run them with automatic savepoint isolation:
-- deploy.sql
BEGIN;
-- ... your migrations ...
-- Run tests with automatic savepoint isolation
-- Each test runs in its own savepoint and rolls back automatically
-- Test failures raise exceptions, aborting the transaction
CALL pgmi_test();
COMMIT;The macro automatically wraps each test in a savepoint, executes it, and rolls back—so test data never persists while your migrations do. If any test fails (via RAISE EXCEPTION), the entire transaction aborts and your database remains unchanged.
Tests are pure PostgreSQL—use RAISE EXCEPTION to fail:
-- __test__/test_users.sql
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM users WHERE email = 'test@example.com') THEN
RAISE EXCEPTION 'Expected user not found';
END IF;
END $$;See Testing Guide for fixtures, hierarchical setup, and the gated deployment pattern.
pgmi supports:
- Standard PostgreSQL — connection strings,
PGPASSWORD,.pgpass - Azure Entra ID — passwordless auth to Azure Database for PostgreSQL
- AWS IAM — token-based auth to Amazon RDS
- Google Cloud SQL IAM — passwordless auth via Cloud SQL Go Connector
# Standard
export PGMI_CONNECTION_STRING="postgresql://user:pass@localhost/postgres"
pgmi deploy . -d mydb
# Azure Entra ID — Managed Identity (no credentials needed)
pgmi deploy . --host myserver.postgres.database.azure.com -d mydb --azure --sslmode require
# Azure Entra ID — Service Principal
export AZURE_TENANT_ID="..." AZURE_CLIENT_ID="..." AZURE_CLIENT_SECRET="..."
pgmi deploy . --host myserver.postgres.database.azure.com -d mydb --azure --sslmode require
# AWS IAM — uses default credential chain (env vars, ~/.aws/credentials, IAM role)
pgmi deploy . --host mydb.abc123.us-west-2.rds.amazonaws.com -d mydb -U myuser --aws --aws-region us-west-2 --sslmode require
# Google Cloud SQL — uses Application Default Credentials (gcloud auth, service account)
pgmi deploy . -d mydb -U myuser@myproject.iam --google --google-instance myproject:us-central1:myinstanceContributions welcome. See CONTRIBUTING.md for guidelines.
Mozilla Public License 2.0. Template code in internal/scaffold/templates/ is MIT licensed—code you generate is yours.
Copyright 2024-2025 Alexey Evlampiev
