# Automatic Database Migrations - Implementation Summary ## What Was Implemented Database migrations now run **automatically** every time the API server starts. This eliminates the need to manually run migration commands. ## Changes Made ### 1. Created Migration Runner (`apps/api/src/db/migrate.ts`) A new module that: - Connects to MySQL using environment variables - Runs pending migrations from the `drizzle/` folder - Provides clear console output with emojis - Handles errors gracefully ```typescript export async function runMigrations() { console.log('🔄 Running database migrations...'); // ... migration logic ... console.log('✅ Database migrations completed successfully'); } ``` ### 2. Integrated into Server Startup (`apps/api/src/index.ts`) Modified the server startup to: - Run migrations before starting Express - Exit with error if migrations fail - Provide clear startup sequence ```typescript async function startServer() { await runMigrations(); // ← Runs automatically app.listen(PORT, () => { console.log(`API server running on port ${PORT}`); }); } ``` ## Benefits ### ✅ **No Manual Steps** - Just run `docker-compose up -d --build` - Migrations run automatically - Database is always up-to-date ### ✅ **Idempotent** - Safe to run multiple times - Only applies new migrations - No duplicate data or errors ### ✅ **Developer Friendly** - Clear console output - Easy to debug - Works in development and production ### ✅ **CI/CD Ready** - No extra deployment steps - Migrations run on container start - Automatic rollout of schema changes ## How It Works ### Startup Sequence ``` 1. Docker starts API container 2. Node.js starts 3. Environment variables loaded (.env) 4. 🔄 Migrations run automatically 5. ✅ Migrations complete 6. Express server starts 7. API ready to accept requests ``` ### Console Output When you start the API, you'll see: ```bash [OpenAIClient] Initialized with timeout: 600s, maxRetries: 2 ENV ADMIN_PASSWORD loaded: true 🔄 Running database migrations... ✅ Database migrations completed successfully API server running on port 3301 ``` ## Testing ### Verify Automatic Migrations ```bash # 1. Reset database (deletes all data!) docker-compose down -v # 2. Start fresh docker-compose up -d --build # 3. Watch the logs docker-compose logs -f api # You should see: # 🔄 Running database migrations... # ✅ Database migrations completed successfully ``` ### Verify Tables Created ```bash docker exec voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog -e "SHOW TABLES;" ``` Expected output: ``` Tables_in_voxblog __drizzle_migrations audio_clips posts settings ``` ## Troubleshooting ### Migrations Don't Run **Check API logs:** ```bash docker-compose logs api | grep -i migration ``` **Common issues:** - MySQL not ready yet (wait 30 seconds) - Wrong database credentials in `.env` - Migration files missing in `apps/api/drizzle/` ### Migration Fails **Error in logs:** ```bash ❌ Migration failed: [error details] ``` **Solutions:** 1. Check MySQL is healthy: `docker-compose ps mysql` 2. Verify credentials in `.env` 3. Check migration files exist: `ls apps/api/drizzle/` 4. Run manually: `docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"` ### Server Won't Start If migrations fail, the server exits with error code 1. **Check logs:** ```bash docker-compose logs api ``` **Restart after fixing:** ```bash docker-compose restart api ``` ## Manual Migration (Still Available) You can still run migrations manually if needed: ```bash # Inside container docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate" # Or using pnpm scripts docker exec voxblog-api pnpm --filter api drizzle:migrate ``` ## Creating New Migrations When you modify the schema (`apps/api/src/db/schema.ts`): ```bash # 1. Generate migration file docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:generate" # 2. Restart API (migrations run automatically) docker-compose restart api # 3. Verify migration applied docker-compose logs api | grep migration ``` ## Production Deployment ### Zero-Downtime Deployment 1. **Build new image** with schema changes 2. **Deploy new container** - migrations run automatically 3. **Old container** continues serving requests 4. **New container** takes over after migrations complete ### Rollback Strategy If a migration fails: 1. Container exits with error 2. Old container keeps running 3. Fix migration and redeploy 4. Or rollback to previous version ## Best Practices ### ✅ **DO** - Test migrations locally first - Make migrations backward compatible - Keep migrations small and focused - Add indexes in separate migrations - Document breaking changes ### ❌ **DON'T** - Don't delete migration files - Don't modify existing migrations - Don't make breaking schema changes without planning - Don't skip testing migrations ## Files Modified 1. **`apps/api/src/db/migrate.ts`** (new) - Migration runner logic - Error handling - Console output 2. **`apps/api/src/index.ts`** (modified) - Import migration runner - Call migrations before server start - Async startup function 3. **`DATABASE_SETUP.md`** (updated) - Document automatic migrations - Update troubleshooting guide - Remove manual migration steps ## Migration History Migrations are tracked in the `__drizzle_migrations` table: ```sql SELECT * FROM __drizzle_migrations; ``` Shows: - Migration ID - Hash - Created timestamp ## Future Enhancements Potential improvements: - Migration rollback command - Migration status endpoint (`/api/migrations`) - Dry-run mode - Migration locking for multi-instance deployments - Slack/email notifications on migration failures --- **Status**: ✅ Implemented and Working **Last Updated**: 2025-10-26 **Author**: Automated Migration System