GitHub (main/staging) → Render Auto-Deploy → Services
| Environment | Branch | Frontend | API | Database |
|---|---|---|---|---|
| Staging | staging |
Render Static Site | Render Web Service | Render Managed Postgres |
| Production | main |
Render Static Site | Render Web Service | Render Managed Postgres |
- All CI checks pass (backend tests, frontend lint/build, CodeQL)
- Migration plan reviewed (if schema changes)
- Environment variables verified for target environment
- Staging deployment tested and verified
- Merge feature branch →
staging - Render auto-deploys frontend and API
- Run smoke tests (see Smoke Test section)
- Verify in staging environment
- Create PR from
staging→main - Review and merge
- Render auto-deploys
- Run production smoke tests
- Monitor error rates and latency for 30 minutes
Migrations are not auto-applied in staging/production. Apply manually:
# From Source/Backend/ directory
dotnet ef database update \
--project src/ASideNote.Infrastructure/ASideNote.Infrastructure.csproj \
--startup-project src/ASideNote.API/ASideNote.API.csproj \
--connection "Host=<host>;Port=5432;Database=<db>;Username=<user>;Password=<password>"Or use the Render Shell to run migrations on the deployed service.
- In Render dashboard, select the API web service
- Go to "Events" → find the last successful deploy
- Click "Rollback to this deploy"
- Repeat for frontend static site if needed
- Verify health checks pass
Warning: Only possible if the migration is reversible (no data loss).
- Roll back the code first (see above)
- Apply the reverse migration:
dotnet ef database update <PreviousMigrationName> \ --project src/ASideNote.Infrastructure/ASideNote.Infrastructure.csproj \ --startup-project src/ASideNote.API/ASideNote.API.csproj \ --connection "<connection-string>"
- Verify application functionality
- Column drops with data
- Table drops
- Data transformations without backup
Rule: All destructive migrations require a manual approval step and a pre-migration backup.
After each deploy, verify:
# Health checks
curl -sf https://api.yourdomain.com/health/live # → 200
curl -sf https://api.yourdomain.com/health/ready # → 200
# Auth endpoint
curl -sf -X POST https://api.yourdomain.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"smoke@test.com","password":"wrong"}' \
-o /dev/null -w "%{http_code}" # → 401 or 403 (not 500)
# Frontend loads
curl -sf https://yourdomain.com/ -o /dev/null -w "%{http_code}" # → 200- Check Render dashboard for deploy status and health check failures
- Check API logs in Render for error patterns
- Verify database connectivity via
/health/ready - Check for recent deploys that may have introduced the issue
- If database-related: check Render Postgres metrics (connections, CPU, storage)
- Escalation path: roll back to last known good deploy, then investigate
- Expand/Contract pattern: Add new columns as nullable first, deploy code that writes to both, then make required in a later migration
- Never drop columns or tables in the same deploy as the code change
- Always test migrations against a copy of production data in staging
- Document migration purpose and reversibility in the migration file name