Production Migration Recovery Guide
Problem: Superadmin Seed Constraint Violation
Root Cause
The seed_superadmin() function was attempting to update is_primary = true on conflict, which violated the unique partial index idx_user_roles_primary_per_user on subsequent application restarts.
Solution Applied
Modified backend/src/infrastructure/database/seed.rs line 60-74 to:
ON CONFLICT (user_id, role, organization_id)
DO UPDATE SET
updated_at = NOW()
-- REMOVED: is_primary = true (prevents constraint violation)
Rationale: is_primary should only be set on INSERT (first run), never on UPDATE (subsequent runs).
Production Deployment Checklist
✅ Pre-Deployment
Backup Database:
pg_dump -U koprogo koprogo_db > backup_$(date +%Y%m%d_%H%M%S).sqlTest on Staging: Deploy to staging environment first
Run Idempotence Tests:
cargo test test_seed_superadmin_is_idempotent
✅ Deployment
Stop Backend:
systemctl stop koprogo-backend(or Docker:docker compose stop backend)Verify Migrations:
SELECT version, checksum FROM _sqlx_migrations ORDER BY version DESC LIMIT 10;
Apply New Code:
git pull && cargo build --releaseStart Backend: Application will auto-seed superadmin idempotently
✅ Post-Deployment Verification
Check Logs:
journalctl -u koprogo-backend | grep superadminExpected:
✅ Superadmin ready: admin@koprogo.comNOT expected:
duplicate key value violates unique constraint
Verify Database State:
-- Should return exactly 1 row SELECT COUNT(*) FROM user_roles WHERE user_id = '00000000-0000-0000-0000-000000000001' AND is_primary = true; -- Should return 1 (superadmin role) SELECT role, is_primary FROM user_roles WHERE user_id = '00000000-0000-0000-0000-000000000001';
Test Login:
curl -X POST http://localhost:8080/api/v1/auth/login -d '{"email":"admin@koprogo.com","password":"admin123"}'
Rollback Plan
If deployment fails:
Stop Backend:
systemctl stop koprogo-backendRestore Backup:
psql -U koprogo koprogo_db < backup_YYYYMMDD_HHMMSS.sqlRevert Code:
git checkout <previous-commit>Start Backend:
systemctl start koprogo-backend
Migration State Recovery (If Needed)
Scenario: Migrations table accidentally modified
⚠️ WARNING: Only use this in extreme cases. Never run in production without full backup.
-- Check current state
SELECT version FROM _sqlx_migrations ORDER BY version DESC;
-- If migrations are missing (e.g., only showing 20240101000006):
-- Option 1: Restore from backup (RECOMMENDED)
-- Option 2: Re-insert migration records (DANGEROUS - only if backup unavailable)
-- DO NOT RUN THIS unless you fully understand the implications:
-- This would require manually re-inserting all missing migration records
-- with correct checksums. Contact DevOps team instead.
Testing Idempotence
Run tests with real PostgreSQL instance:
# Local dev
cargo test --test integration test_seed_superadmin_is_idempotent
# CI/CD
docker compose -f docker-compose.test.yml run --rm backend cargo test --lib test_seed_superadmin
Monitoring
Add alerting for:
Application startup failures (check for constraint violations in logs)
Unexpected
user_rolesrecord counts for superadminFailed login attempts for
admin@koprogo.com
Questions?
Contact: DevOps Team | Created: 2025-12-06