Production Deployment
Production deployment is where everything counts. Every migration affects real users and real data. This guide walks you through deploying to production safely and confidently.
The Production Mindset
flowchart LR A["Staging ✅"] --> B["Review Changes"] B --> C["Backup Data"] C --> D["Apply Migrations"] D --> E["Deploy Code"] E --> F["Verify & Monitor"]
Production deployments require extra diligence:
- Test everything in staging first - No exceptions
- Have a rollback plan - Know how to recover before you deploy
- Deploy during low-traffic periods - Minimize user impact
- Monitor after deployment - Catch issues early
Prerequisites
Before deploying to production, ensure:
- Staging deployment successful - All changes validated (see Staging Deployment)
- Migrations tested - Applied and verified in staging
- Team notified - Stakeholders aware of the deployment
- Rollback plan ready - Know exactly what to do if something fails
Step 1: Create the Production Database
Create your production D1 database on Cloudflare.
Creating the Database
pnpm wrangler d1 create d1-migration-mastery-productionExpected output:
✅ Successfully created DB 'd1-migration-mastery-production' in region WNAMCreated your new D1 database.
[[d1_databases]]binding = "DB"database_name = "d1-migration-mastery-production"database_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"Adding to wrangler.toml
Add the production database configuration:
# Production Environment[env.production]name = "d1-migration-mastery-production"
[[env.production.d1_databases]]binding = "DB"database_name = "d1-migration-mastery-production"database_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"migrations_dir = "migrations"Verifying the Database
Confirm your production database exists:
pnpm wrangler d1 listExpected output:
┌────────────────────────────────────┬──────────────────────────────────────┬────────┐│ Name │ ID │ Region │├────────────────────────────────────┼──────────────────────────────────────┼────────┤│ d1-migration-mastery-staging │ f1e2d3c4-b5a6-0987-fedc-ba0987654321 │ WNAM │├────────────────────────────────────┼──────────────────────────────────────┼────────┤│ d1-migration-mastery-production │ a1b2c3d4-e5f6-7890-abcd-ef1234567890 │ WNAM │└────────────────────────────────────┴──────────────────────────────────────┴────────┘Step 2: Safe Migration Practices
Production migrations require careful planning and execution.
Pre-Migration Checklist
Before running any production migration:
flowchart TD A["Pre-Migration Checklist"] --> B["✅ Tested in staging?"] B --> C["✅ Reviewed migration SQL?"] C --> D["✅ Backup strategy ready?"] D --> E["✅ Rollback plan documented?"] E --> F["✅ Low-traffic period?"] F --> G["✅ Team notified?"] G --> H["Proceed with Migration"]
| Check | Description |
|---|---|
| Tested in staging | Migration ran successfully without errors |
| Reviewed SQL | Verified the generated SQL does what you expect |
| Backup ready | Know how to restore if needed |
| Rollback documented | Written steps to undo changes |
| Low traffic | Deploying during off-peak hours |
| Team notified | Everyone knows deployment is happening |
Reviewing Migration Files
Always review what will be executed:
# List pending migrationspnpm wrangler d1 migrations list DB --remote --env productionExpected output (before applying):
Migrations:┌─────────────────────────────────────┬────────────────────┐│ name │ status │├─────────────────────────────────────┼────────────────────┤│ 0000_initial.sql │ ✅ Applied │├─────────────────────────────────────┼────────────────────┤│ 0001_add_user_profile.sql │ ✅ Applied │├─────────────────────────────────────┼────────────────────┤│ 0002_add_posts.sql │ ⏳ Pending │└─────────────────────────────────────┴────────────────────┘Reading the Migration SQL
Read the actual SQL before applying:
cat migrations/0002_add_posts.sqlLook for:
- Destructive operations -
DROP TABLE,DROP COLUMN - Data modifications -
UPDATE,DELETE - Schema changes - Understand exactly what’s changing
Applying Production Migrations
Once verified, apply the migration:
pnpm wrangler d1 migrations apply DB --remote --env productionExpected output:
Migrations to be applied:┌─────────────────────────────────────┐│ name │├─────────────────────────────────────┤│ 0002_add_posts.sql │└─────────────────────────────────────┘
✔ About to apply 1 migration(s)Your database may not be available to serve requests during the migration, continue? … yes🌀 Executing on remote database DB (a1b2c3d4-e5f6-7890-abcd-ef1234567890):
Applying migration: 0002_add_posts.sql Running query 1/2: CREATE TABLE `posts`... ✔ Query 1/2 succeeded Running query 2/2: CREATE INDEX... ✔ Query 2/2 succeeded✔ Applied 0002_add_posts.sql
✅ 1 migration(s) applied successfullyStep 3: Deploy the Application
With migrations applied, deploy your Worker code.
Deploying to Production
pnpm wrangler deploy --env productionExpected output:
⛅️ wrangler 3.x.x-------------------Your worker has access to the following bindings:- D1 Databases: - DB: d1-migration-mastery-production (a1b2c3d4-e5f6-7890-abcd-ef1234567890)Total Upload: 150.23 KiB / gzip: 35.67 KiBWorker Startup Time: 15 msUploaded d1-migration-mastery-production (2.50 sec)Published d1-migration-mastery-production (0.35 sec) https://d1-migration-mastery-production.<your-subdomain>.workers.devCurrent Deployment ID: prod123-abc456-def789Current Version ID: version-abc123-xyzVerifying Deployment
Test that the deployment was successful:
# Quick health checkcurl https://d1-migration-mastery-production.<your-subdomain>.workers.dev/health
# Or test an API endpointcurl https://d1-migration-mastery-production.<your-subdomain>.workers.dev/usersStep 4: Rollback Strategies
Things can go wrong. Have a plan ready before you need it.
flowchart TD
A["Issue Detected"] --> B{What failed?}
B -->|"Code bug"| C["Rollback Code"]
B -->|"Migration broke data"| D["Restore from Backup"]
B -->|"Both"| E["Rollback Code + Restore Data"]
C --> F["Deploy previous version"]
D --> G["Use D1 Time Travel"]
E --> H["Coordinate both"]
F --> I["Verify fix"]
G --> I
H --> I
Strategy 1: Rollback Code Only
If the issue is in your Worker code (not the migration):
# List recent deploymentspnpm wrangler deployments list --env production
# Rollback to previous versionpnpm wrangler rollback --env productionExpected output:
⛅️ wrangler 3.x.x-------------------Successfully rolled back to deployment prod122-abc456-def788Current Version ID: version-abc122-xyzStrategy 2: Restore Database from Backup
D1 supports point-in-time recovery using Time Travel:
# List available bookmarks (restore points)pnpm wrangler d1 time-travel info DB --env production
# Restore to a specific point in time (within last 30 days)pnpm wrangler d1 time-travel restore DB --env production --timestamp "2024-01-15T10:00:00Z"Strategy 3: Forward-Fix Migration
Sometimes the best approach is a new migration that fixes the issue:
# Generate a fix migrationpnpm drizzle-kit generate --name fix_column_issue
# Apply the fixpnpm wrangler d1 migrations apply DB --remote --env productionStrategy 4: Manual SQL Fix
For urgent issues, execute SQL directly:
# Execute a fix directly (use with caution)pnpm wrangler d1 execute DB --remote --env production \ --command "UPDATE users SET status = 'active' WHERE status IS NULL"When to Use Each Strategy
| Scenario | Strategy |
|---|---|
| Code bug, data is fine | Rollback code |
| Migration corrupted data | Restore from backup |
| Missing column or index | Forward-fix migration |
| Simple data correction | Manual SQL fix |
| Major outage | Rollback code + restore data |
Production Deployment Checklist
Use this checklist for every production deployment:
Before Deployment
| Check | Status |
|---|---|
| Changes tested in staging | ⬜ |
| Migration SQL reviewed | ⬜ |
| Rollback plan documented | ⬜ |
| Team notified of deployment | ⬜ |
| Low-traffic period selected | ⬜ |
| Monitoring dashboards open | ⬜ |
During Deployment
| Step | Command | Status |
|---|---|---|
| Check pending migrations | pnpm wrangler d1 migrations list DB --remote --env production | ⬜ |
| Apply migrations | pnpm wrangler d1 migrations apply DB --remote --env production | ⬜ |
| Deploy Worker | pnpm wrangler deploy --env production | ⬜ |
| Verify deployment | Visit production URL | ⬜ |
After Deployment
| Check | Status |
|---|---|
| API endpoints responding | ⬜ |
| No errors in logs | ⬜ |
| Database queries working | ⬜ |
| Performance acceptable | ⬜ |
| Team notified of completion | ⬜ |
Post-Deployment Monitoring
After deployment, actively monitor for issues.
Watching Logs
Stream real-time logs from production:
pnpm wrangler tail --env productionExpected output:
⬣ Listening for logs...[2024-01-15 10:30:45] GET /users 200 OK (45ms)[2024-01-15 10:30:46] POST /users 201 Created (120ms)[2024-01-15 10:30:47] GET /users/1 200 OK (35ms)Key Metrics to Watch
Monitor these in the Cloudflare dashboard:
| Metric | Healthy Range | Action if Unhealthy |
|---|---|---|
| Error rate | < 1% | Check logs, rollback if needed |
| Response time | < 200ms | Investigate slow queries |
| Request volume | Normal for time of day | Verify no traffic drop |
| CPU time | < 10ms average | Optimize heavy operations |
Checking Database Health
Verify database is performing well:
# Check table sizespnpm wrangler d1 execute DB --remote --env production \ --command "SELECT name, COUNT(*) as rows FROM sqlite_master WHERE type='table'"
# Verify recent datapnpm wrangler d1 execute DB --remote --env production \ --command "SELECT COUNT(*) FROM users WHERE createdAt > datetime('now', '-1 hour')"Quick Reference
| Task | Command |
|---|---|
| Create production database | pnpm wrangler d1 create <name> |
| List migrations | pnpm wrangler d1 migrations list DB --remote --env production |
| Apply migrations | pnpm wrangler d1 migrations apply DB --remote --env production |
| Deploy to production | pnpm wrangler deploy --env production |
| View production logs | pnpm wrangler tail --env production |
| Rollback deployment | pnpm wrangler rollback --env production |
| Execute SQL | pnpm wrangler d1 execute DB --remote --env production --command "..." |
Summary
Safe production deployment follows these principles:
- Always test in staging first - No shortcuts
- Review migrations before applying - Know exactly what will run
- Have a rollback plan - Document it before you deploy
- Monitor after deployment - Catch issues before users report them
- Deploy during low-traffic periods - Minimize user impact
With these practices, you can deploy to production confidently and recover quickly if issues arise.