Use when setting up database backups, recovering from data loss, implementing point-in-time recovery, or planning disaster recovery for PostgreSQL/Supabase - focuses on backup strategies and data restoration
☐ Supabase automatic backups (daily) ☐ Manual pg_dump backups ☐ Point-in-time recovery (PITR) ☐ Logical vs. physical backups
Supabase Backup Features:
☐ Connect to database with pg_dump ☐ Choose backup format (custom, plain SQL) ☐ Include schema and data ☐ Store backup securely
Create full database backup:
# Custom format (compressed, recommended)
pg_dump -Fc \
-h db.your-project.supabase.co \
-U postgres \
-d postgres \
-f backup_$(date +%Y%m%d_%H%M%S).dump
# Plain SQL format (human-readable)
pg_dump -h db.your-project.supabase.co \
-U postgres \
-d postgres \
-f backup.sql
Backup specific tables:
# Backup only specific tables
pg_dump -Fc \
-h db.your-project.supabase.co \
-U postgres \
-d postgres \
-t documents -t users \
-f partial_backup.dump
Schema only (no data):
# Backup schema structure only
pg_dump --schema-only \
-h db.your-project.supabase.co \
-U postgres \
-d postgres \
-f schema_only.sql
☐ Create backup script ☐ Schedule with cron or task scheduler ☐ Rotate old backups ☐ Monitor backup success
Backup script (backup.sh):
#!/bin/bash
set -e
# Configuration
DB_HOST="db.your-project.supabase.co"
DB_USER="postgres"
DB_NAME="postgres"
BACKUP_DIR="/backups"
RETENTION_DAYS=30
# Create backup
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_$TIMESTAMP.dump"
pg_dump -Fc -h $DB_HOST -U $DB_USER -d $DB_NAME -f $BACKUP_FILE
# Compress
gzip $BACKUP_FILE
# Delete old backups
find $BACKUP_DIR -name "backup_*.dump.gz" -mtime +$RETENTION_DAYS -delete
# Upload to cloud storage (optional)
# aws s3 cp $BACKUP_FILE.gz s3://my-backups/
Schedule with cron (daily at 2 AM):
# Edit crontab
crontab -e
# Add line:
0 2 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1
☐ Identify backup file to restore ☐ Create new database or clear existing ☐ Restore with pg_restore ☐ Verify data restoration
Restore custom format backup:
# Restore to new database
pg_restore -Fc \
-h db.your-project.supabase.co \
-U postgres \
-d postgres \
--clean --if-exists \
backup.dump
Restore plain SQL backup:
# Restore SQL file
psql -h db.your-project.supabase.co \
-U postgres \
-d postgres \
-f backup.sql
Restore specific tables:
# Restore only certain tables
pg_restore -Fc \
-h db.your-project.supabase.co \
-U postgres \
-d postgres \
-t documents -t users \
backup.dump
☐ Identify timestamp to restore to ☐ Use Supabase dashboard PITR feature ☐ Create new project from specific time ☐ Verify restored data
PITR via Supabase Dashboard:
☐ Create test database ☐ Restore backup to test database ☐ Verify data completeness ☐ Document restore time
Test restore locally:
# Create test database
createdb test_restore
# Restore backup
pg_restore -Fc -d test_restore backup.dump
# Verify row counts
psql -d test_restore -c "SELECT COUNT(*) FROM documents;"
# Cleanup
dropdb test_restore
☐ Export specific data with queries ☐ Use COPY or pg_dump with WHERE clause ☐ Restore to temporary table ☐ Merge into production
Export specific data:
-- Copy data to CSV
COPY (
SELECT * FROM documents
WHERE created_at > '2023-01-01'
) TO '/tmp/recent_documents.csv' CSV HEADER;
Import specific data:
-- Import CSV to table
COPY documents FROM '/tmp/recent_documents.csv' CSV HEADER;
☐ Document backup locations ☐ Test restore procedures quarterly ☐ Assign recovery responsibilities ☐ Set RTO/RPO targets
Recovery Time Objective (RTO):
Recovery Point Objective (RPO):
Example:
# Full backup weekly
pg_dump -Fc -f full_backup_$(date +%Y%m%d).dump
# Incremental (changes only) - requires WAL archiving
# Use Supabase PITR for this
-- If caught immediately, use PITR
-- Or restore from most recent backup
-- If partial, restore to temp database
pg_restore -Fc -d temp_db backup.dump
-- Copy data back
INSERT INTO production.documents
SELECT * FROM temp_db.documents;
-- Restore to temp table
CREATE TEMP TABLE documents_backup AS
SELECT * FROM documents WHERE false;
-- Load from backup
-- (restore to temp database, then copy)
-- Merge missing rows
INSERT INTO documents
SELECT * FROM temp_db.documents
WHERE id NOT IN (SELECT id FROM documents);
Never:
Always:
Supabase Specific:
Weekly:
Monthly:
Quarterly: