← Back to blog

PostgreSQL Migration Steps: Practical Guide

· 3 min read · Stew Team
database migration stepspostgresqldatabase

PostgreSQL powers some of the world’s most critical applications. When you need to migrate a Postgres database, you need database migration steps that account for its specific features and quirks.

This guide covers PostgreSQL-specific database migration steps that leverage Postgres tools and best practices. For general migration guidance, start with our database migration steps checklist.

PostgreSQL Database Migration Steps

Step 1: Assess Your Database

Before migrating, understand what you’re working with:

-- Database size
SELECT pg_size_pretty(pg_database_size(current_database()));

-- Table sizes
SELECT schemaname, tablename, 
       pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename))
FROM pg_tables 
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC;

-- Check for active connections
SELECT count(*) FROM pg_stat_activity WHERE datname = current_database();

Step 2: Create a Consistent Backup

Use pg_dump with appropriate flags:

# Full backup with compression
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME \
  --format=custom \
  --compress=9 \
  --file=backup_$(date +%Y%m%d_%H%M%S).dump

# Schema only (for testing migrations)
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME \
  --schema-only \
  --file=schema_backup.sql

Step 3: Handle Sequences Correctly

PostgreSQL sequences often cause migration issues:

-- Check current sequence values
SELECT sequencename, last_value 
FROM pg_sequences 
WHERE schemaname = 'public';

-- After migration, reset sequences if needed
SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));

Step 4: Manage Constraints During Migration

For large data migrations, temporarily disable constraints:

-- Disable triggers (including FK checks)
ALTER TABLE orders DISABLE TRIGGER ALL;

-- Run your migration
INSERT INTO orders SELECT * FROM legacy_orders;

-- Re-enable triggers
ALTER TABLE orders ENABLE TRIGGER ALL;

-- Verify constraints
ALTER TABLE orders VALIDATE CONSTRAINT orders_user_id_fkey;

Step 5: Use PostgreSQL-Specific Features

Leverage Postgres capabilities for safer migrations:

-- Concurrent index creation (no table locks)
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);

-- Add column with default (instant in PG 11+)
ALTER TABLE users ADD COLUMN status VARCHAR(50) DEFAULT 'active';

-- Online column type changes (when possible)
ALTER TABLE users ALTER COLUMN age TYPE INTEGER USING age::INTEGER;

Step 6: Monitor PostgreSQL During Migration

-- Watch for blocking queries
SELECT blocked_locks.pid AS blocked_pid,
       blocking_locks.pid AS blocking_pid,
       blocked_activity.query AS blocked_query
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_locks blocking_locks 
  ON blocking_locks.locktype = blocked_locks.locktype
WHERE NOT blocked_locks.granted;

-- Check replication lag (if applicable)
SELECT client_addr, state, 
       pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes
FROM pg_stat_replication;

Step 7: Verify with PostgreSQL Tools

# Restore to test database
pg_restore -h $STAGING_HOST -U $DB_USER -d test_db backup.dump

# Compare schemas
pg_dump --schema-only production_db > prod_schema.sql
pg_dump --schema-only test_db > test_schema.sql
diff prod_schema.sql test_schema.sql

Automating PostgreSQL Database Migration Steps

PostgreSQL migrations involve many commands that must run in sequence. Missing one step—like resetting sequences—causes subtle bugs that surface days later. For production-specific guidance, see database migration steps for production and our best practices guide.

Stew lets you document your PostgreSQL database migration steps as executable Markdown. Run each psql command with a click. Track progress automatically. Share proven procedures with your team.

Join the waitlist and make PostgreSQL migrations reliable.