- Added new migrate.ts module to handle automatic database migrations using drizzle-orm - Modified server startup to run migrations before Express initialization - Added comprehensive documentation in AUTO_MIGRATION_SUMMARY.md explaining the implementation - Updated DATABASE_SETUP.md to reflect automatic migration process and troubleshooting steps - Added error handling to exit process if migrations fail during startup - Implemented clear
5.7 KiB
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
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
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:
[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
# 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
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:
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:
❌ Migration failed: [error details]
Solutions:
- Check MySQL is healthy:
docker-compose ps mysql - Verify credentials in
.env - Check migration files exist:
ls apps/api/drizzle/ - 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:
docker-compose logs api
Restart after fixing:
docker-compose restart api
Manual Migration (Still Available)
You can still run migrations manually if needed:
# 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):
# 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
- Build new image with schema changes
- Deploy new container - migrations run automatically
- Old container continues serving requests
- New container takes over after migrations complete
Rollback Strategy
If a migration fails:
- Container exits with error
- Old container keeps running
- Fix migration and redeploy
- 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
-
apps/api/src/db/migrate.ts(new)- Migration runner logic
- Error handling
- Console output
-
apps/api/src/index.ts(modified)- Import migration runner
- Call migrations before server start
- Async startup function
-
DATABASE_SETUP.md(updated)- Document automatic migrations
- Update troubleshooting guide
- Remove manual migration steps
Migration History
Migrations are tracked in the __drizzle_migrations table:
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