|
| 1 | +# Database Deployment Checklist |
| 2 | + |
| 3 | +Use this checklist when deploying the database to a new environment. |
| 4 | + |
| 5 | +## 📋 Pre-Deployment |
| 6 | + |
| 7 | +- [ ] PostgreSQL 14+ installed and running |
| 8 | +- [ ] TimescaleDB extension available (optional but recommended) |
| 9 | +- [ ] Database created: `createdb devlog` |
| 10 | +- [ ] Database URL set in environment: `export DATABASE_URL="postgresql://..."` |
| 11 | +- [ ] Database user has required permissions (CREATE, ALTER, DROP) |
| 12 | +- [ ] Network connectivity verified: `psql $DATABASE_URL -c "SELECT version();"` |
| 13 | + |
| 14 | +## 🚀 Deployment Steps |
| 15 | + |
| 16 | +### 1. Initialize Database Extensions |
| 17 | + |
| 18 | +```bash |
| 19 | +psql $DATABASE_URL -f scripts/database/init-db.sql |
| 20 | +``` |
| 21 | + |
| 22 | +**Expected output**: Extensions created |
| 23 | + |
| 24 | +- [x] uuid-ossp |
| 25 | +- [x] pg_trgm |
| 26 | + |
| 27 | +### 2. Apply Prisma Migrations |
| 28 | + |
| 29 | +```bash |
| 30 | +npx prisma migrate deploy |
| 31 | +``` |
| 32 | + |
| 33 | +**Expected output**: All migrations applied successfully |
| 34 | + |
| 35 | +Verify: |
| 36 | + |
| 37 | +```bash |
| 38 | +npx prisma migrate status |
| 39 | +``` |
| 40 | + |
| 41 | +### 3. Generate Prisma Client |
| 42 | + |
| 43 | +```bash |
| 44 | +npx prisma generate |
| 45 | +``` |
| 46 | + |
| 47 | +**Expected output**: Prisma Client generated |
| 48 | + |
| 49 | +### 4. Enable TimescaleDB (Optional) |
| 50 | + |
| 51 | +```bash |
| 52 | +psql $DATABASE_URL -f scripts/enable-timescaledb.sql |
| 53 | +``` |
| 54 | + |
| 55 | +**Expected output**: |
| 56 | + |
| 57 | +- [x] TimescaleDB extension created |
| 58 | +- [x] agent_events converted to hypertable |
| 59 | +- [x] Compression enabled |
| 60 | +- [x] Retention policy set (1 year) |
| 61 | +- [x] Continuous aggregates created (hourly, daily) |
| 62 | + |
| 63 | +Verify: |
| 64 | + |
| 65 | +```bash |
| 66 | +psql $DATABASE_URL -c "SELECT * FROM timescaledb_information.hypertables;" |
| 67 | +``` |
| 68 | + |
| 69 | +## ✅ Post-Deployment Verification |
| 70 | + |
| 71 | +### Database Health |
| 72 | + |
| 73 | +```bash |
| 74 | +# Check database size |
| 75 | +psql $DATABASE_URL -c "SELECT pg_size_pretty(pg_database_size(current_database()));" |
| 76 | + |
| 77 | +# List all tables |
| 78 | +psql $DATABASE_URL -c "\dt" |
| 79 | + |
| 80 | +# Expected tables: |
| 81 | +# - projects, machines, workspaces |
| 82 | +# - chat_sessions, chat_messages |
| 83 | +# - agent_events, agent_sessions |
| 84 | +# - devlog_entries, devlog_notes, devlog_dependencies, devlog_documents |
| 85 | +# - users, user_providers, email_verification_tokens, password_reset_tokens |
| 86 | +``` |
| 87 | + |
| 88 | +### TimescaleDB (if enabled) |
| 89 | + |
| 90 | +```bash |
| 91 | +# Check hypertables |
| 92 | +psql $DATABASE_URL -c "SELECT * FROM timescaledb_information.hypertables;" |
| 93 | + |
| 94 | +# Check continuous aggregates |
| 95 | +psql $DATABASE_URL -c "SELECT * FROM timescaledb_information.continuous_aggregates;" |
| 96 | + |
| 97 | +# Expected views: |
| 98 | +# - agent_events_hourly |
| 99 | +# - agent_events_daily |
| 100 | +``` |
| 101 | + |
| 102 | +### Application Test |
| 103 | + |
| 104 | +```bash |
| 105 | +# Test application startup |
| 106 | +pnpm dev:web |
| 107 | + |
| 108 | +# Check health endpoint (if available) |
| 109 | +curl http://localhost:3000/api/health |
| 110 | +``` |
| 111 | + |
| 112 | +## 🔍 Troubleshooting |
| 113 | + |
| 114 | +### Issue: Permission denied |
| 115 | + |
| 116 | +```bash |
| 117 | +# Grant necessary permissions |
| 118 | +psql $DATABASE_URL -c "GRANT CREATE ON DATABASE devlog TO your_user;" |
| 119 | +``` |
| 120 | + |
| 121 | +### Issue: Extension not available |
| 122 | + |
| 123 | +```bash |
| 124 | +# Check available extensions |
| 125 | +psql $DATABASE_URL -c "SELECT * FROM pg_available_extensions ORDER BY name;" |
| 126 | + |
| 127 | +# For TimescaleDB, install separately |
| 128 | +# See: https://docs.timescale.com/install/latest/ |
| 129 | +``` |
| 130 | + |
| 131 | +### Issue: Migration conflicts |
| 132 | + |
| 133 | +```bash |
| 134 | +# Check migration status |
| 135 | +npx prisma migrate status |
| 136 | + |
| 137 | +# If conflicts exist, resolve manually |
| 138 | +npx prisma migrate resolve --applied migration_name |
| 139 | +``` |
| 140 | + |
| 141 | +### Issue: Connection refused |
| 142 | + |
| 143 | +```bash |
| 144 | +# Check if PostgreSQL is running |
| 145 | +pg_isready -h localhost -p 5432 |
| 146 | + |
| 147 | +# Check if database exists |
| 148 | +psql -l | grep devlog |
| 149 | + |
| 150 | +# Test connection |
| 151 | +psql $DATABASE_URL -c "SELECT version();" |
| 152 | +``` |
| 153 | + |
| 154 | +## 📊 Performance Monitoring Setup |
| 155 | + |
| 156 | +### Enable Query Logging |
| 157 | + |
| 158 | +```sql |
| 159 | +-- Edit postgresql.conf or set in psql |
| 160 | +ALTER SYSTEM SET log_min_duration_statement = '1000'; -- Log queries > 1s |
| 161 | +ALTER SYSTEM SET log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '; |
| 162 | +SELECT pg_reload_conf(); |
| 163 | +``` |
| 164 | + |
| 165 | +### Create Monitoring Views |
| 166 | + |
| 167 | +```sql |
| 168 | +-- Slow queries view |
| 169 | +CREATE VIEW slow_queries AS |
| 170 | +SELECT |
| 171 | + pid, |
| 172 | + now() - query_start as duration, |
| 173 | + usename, |
| 174 | + query |
| 175 | +FROM pg_stat_activity |
| 176 | +WHERE state = 'active' |
| 177 | + AND query_start < now() - interval '5 seconds' |
| 178 | +ORDER BY duration DESC; |
| 179 | + |
| 180 | +-- Table sizes view |
| 181 | +CREATE VIEW table_sizes AS |
| 182 | +SELECT |
| 183 | + tablename, |
| 184 | + pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size, |
| 185 | + pg_total_relation_size(schemaname||'.'||tablename) as bytes |
| 186 | +FROM pg_tables |
| 187 | +WHERE schemaname = 'public' |
| 188 | +ORDER BY bytes DESC; |
| 189 | +``` |
| 190 | + |
| 191 | +## 🔐 Security Hardening |
| 192 | + |
| 193 | +### Database User Permissions |
| 194 | + |
| 195 | +```sql |
| 196 | +-- Create limited application user |
| 197 | +CREATE USER devlog_app WITH PASSWORD 'secure_password'; |
| 198 | + |
| 199 | +-- Grant minimal permissions |
| 200 | +GRANT CONNECT ON DATABASE devlog TO devlog_app; |
| 201 | +GRANT USAGE ON SCHEMA public TO devlog_app; |
| 202 | +GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO devlog_app; |
| 203 | +GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO devlog_app; |
| 204 | + |
| 205 | +-- Update connection string to use limited user |
| 206 | +-- DATABASE_URL="postgresql://devlog_app:secure_password@host:5432/devlog" |
| 207 | +``` |
| 208 | + |
| 209 | +### Enable SSL |
| 210 | + |
| 211 | +```bash |
| 212 | +# Update connection string |
| 213 | +DATABASE_URL="postgresql://user:password@host:5432/devlog?sslmode=require" |
| 214 | +``` |
| 215 | + |
| 216 | +### Network Security |
| 217 | + |
| 218 | +- [ ] Firewall rules configured (only allow necessary IPs) |
| 219 | +- [ ] SSL/TLS enabled for remote connections |
| 220 | +- [ ] Strong passwords for all database users |
| 221 | +- [ ] Regular security updates applied |
| 222 | + |
| 223 | +## 📦 Backup Setup |
| 224 | + |
| 225 | +### Automated Backups |
| 226 | + |
| 227 | +```bash |
| 228 | +# Add to crontab (daily backup at 2 AM) |
| 229 | +0 2 * * * pg_dump -Fc devlog > /backups/devlog_$(date +\%Y\%m\%d).dump |
| 230 | + |
| 231 | +# Weekly full backup |
| 232 | +0 2 * * 0 pg_dumpall > /backups/full_backup_$(date +\%Y\%m\%d).sql |
| 233 | + |
| 234 | +# Retention: keep 30 days |
| 235 | +find /backups -name "devlog_*.dump" -mtime +30 -delete |
| 236 | +``` |
| 237 | + |
| 238 | +### Test Restore |
| 239 | + |
| 240 | +```bash |
| 241 | +# Test restore in separate database |
| 242 | +createdb devlog_test |
| 243 | +pg_restore -d devlog_test /backups/devlog_20251101.dump |
| 244 | +dropdb devlog_test |
| 245 | +``` |
| 246 | + |
| 247 | +## 📈 Monitoring Alerts |
| 248 | + |
| 249 | +Set up alerts for: |
| 250 | + |
| 251 | +- [ ] Database size > 80% capacity |
| 252 | +- [ ] Slow queries (> 5 seconds) |
| 253 | +- [ ] Connection pool exhaustion |
| 254 | +- [ ] Failed backups |
| 255 | +- [ ] Disk space < 20% |
| 256 | +- [ ] Replication lag (if using replication) |
| 257 | + |
| 258 | +## ✅ Deployment Complete |
| 259 | + |
| 260 | +- [ ] All steps completed successfully |
| 261 | +- [ ] Verification checks passed |
| 262 | +- [ ] Monitoring configured |
| 263 | +- [ ] Backups scheduled |
| 264 | +- [ ] Security hardened |
| 265 | +- [ ] Documentation updated with deployment details |
| 266 | + |
| 267 | +**Date Deployed**: ******\_****** |
| 268 | +**Deployed By**: ******\_****** |
| 269 | +**Environment**: ******\_****** |
| 270 | +**Database Version**: ******\_****** |
| 271 | +**TimescaleDB Version**: ******\_****** (if applicable) |
| 272 | + |
| 273 | +--- |
| 274 | + |
| 275 | +**Next Steps**: |
| 276 | + |
| 277 | +1. Monitor application logs for database errors |
| 278 | +2. Check query performance metrics |
| 279 | +3. Verify continuous aggregates are refreshing |
| 280 | +4. Test backup and restore procedures |
| 281 | +5. Document any issues and resolutions |
| 282 | + |
| 283 | +**Support Resources**: |
| 284 | + |
| 285 | +- Database Setup Guide: `scripts/database/README.md` |
| 286 | +- Quick Reference: `scripts/database/QUICK_REFERENCE.md` |
| 287 | +- Troubleshooting: See README.md section |
0 commit comments