-
Notifications
You must be signed in to change notification settings - Fork 3
Production Deployment
Complete guide to deploying D1 Database Manager to Cloudflare Workers for production use.
Before deploying, ensure you have:
- β Cloudflare account (Sign up free)
- β
Wrangler CLI installed (
npm install -g wrangler) - β Domain in Cloudflare (optional - can use workers.dev)
- β D1 Manager source code
- β Cloudflare Access configured (see Authentication Setup)
Local Development β Build Frontend β Configure Worker β Set Secrets β Deploy
# Install globally
npm install -g wrangler
# Or use with npx (no global install needed)
npx wrangler --versionwrangler loginThis opens a browser for authentication. Grant access when prompted.
Verify authentication:
wrangler whoamiEdit wrangler.toml with your configuration:
name = "d1-manager"
main = "worker/index.ts"
compatibility_date = "2024-10-15"
workers_dev = false
# Asset configuration for serving frontend
[assets]
directory = "dist"
binding = "ASSETS"
# Optional: Custom domain routing
[[routes]]
pattern = "d1.yourdomain.com/*"
zone_name = "yourdomain.com"
# D1 database binding
[[d1_databases]]
binding = "DB"
database_name = "d1-manager-metadata"
database_id = "" # Fill in after Step 4
# Enable observability
[observability]
enabled = trueConfiguration Notes:
- Replace
d1.yourdomain.comwith your domain - Replace
yourdomain.comwith your zone name - Leave
database_idempty for now (filled in Step 4)
Create the D1 database for storing query history and saved queries:
# Create database
wrangler d1 create d1-manager-metadataOutput:
β
Successfully created DB 'd1-manager-metadata'!
[[d1_databases]]
binding = "DB"
database_name = "d1-manager-metadata"
database_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Copy the database_id and add it to your wrangler.toml.
Initialize the schema:
wrangler d1 execute d1-manager-metadata --remote --file=worker/schema.sqlNote for existing users upgrading: If you're upgrading from an earlier version, run this command again to add new tables (like undo_history for the rollback feature). Existing tables won't be affected:
# Safe to run on existing metadata database
wrangler d1 execute d1-manager-metadata --remote --file=worker/schema.sqlVerify:
wrangler d1 execute d1-manager-metadata --remote --command="SELECT name FROM sqlite_master WHERE type='table';"You should see tables including: query_history, saved_queries, and undo_history.
To enable database backups to R2 storage:
# Create the R2 bucket
npx wrangler r2 bucket create d1-manager-backupsAdd R2 and Durable Object configuration to your wrangler.toml:
# R2 Backup Bucket
[[r2_buckets]]
binding = "BACKUP_BUCKET"
bucket_name = "d1-manager-backups"
# Durable Objects for async backup processing
[[durable_objects.bindings]]
name = "BACKUP_DO"
class_name = "BackupDO"
script_name = "d1-manager"
[[migrations]]
tag = "v1"
new_classes = ["BackupDO"]Note: The
wrangler.tomlincludes this configuration. R2 backup enables cloud storage for database backups with one-click restore. See R2-Backup-Restore for complete documentation.
See Authentication Setup for complete instructions.
Quick checklist:
- β Identity provider configured (GitHub, Google, etc.)
- β Access application created
- β Policies configured
- β Application AUD tag obtained
- β Team domain obtained
Set all required secrets using Wrangler:
# Cloudflare Account ID
wrangler secret put ACCOUNT_ID
# Enter: your-account-id
# Cloudflare API Token (with D1 Edit permission)
wrangler secret put API_KEY
# Enter: your-api-token
# Cloudflare Access Team Domain
wrangler secret put TEAM_DOMAIN
# Enter: https://yourteam.cloudflareaccess.com
# Cloudflare Access Application AUD
wrangler secret put POLICY_AUD
# Enter: your-aud-tagFind your Account ID:
Dashboard URL: https://dash.cloudflare.com/YOUR_ACCOUNT_ID
Create API Token:
- Go to API Tokens
- Click Create Token β Create Custom Token
- Name:
D1-Manager-Token - Permissions: Account β D1 β Edit
- Click Create Token
- Copy the token (shown only once)
Verify secrets:
wrangler secret listEdit .env to disable local API:
# .env (production)
# Comment out or remove this line
# VITE_WORKER_API=http://localhost:8787
# When undefined, app uses window.location.origin# Install dependencies (if not already done)
npm install
# Build production bundle
npm run buildOutput:
vite v7.1.12 building for production...
β 1234 modules transformed.
dist/index.html 0.45 kB β gzip: 0.30 kB
dist/assets/index-CkbgeJUQ.css 45.23 kB β gzip: 8.12 kB
dist/assets/index-CNIKIAND.js 456.78 kB β gzip: 123.45 kB
β built in 5.67s
Verify build:
ls -lh dist/# Deploy everything
wrangler deployOutput:
Total Upload: 512.34 KiB / gzip: 145.67 KiB
Uploaded d1-manager (1.23 sec)
Published d1-manager (2.34 sec)
https://d1-manager.your-account.workers.dev
https://d1.yourdomain.com (custom domain)
Current Deployment ID: abc123def456
-
Visit your Worker URL:
https://d1-manager.your-account.workers.dev- Or
https://d1.yourdomain.com(custom domain)
-
You should see:
- Cloudflare Access login page
- Authenticate with your identity provider
- D1 Manager interface loads
- Real D1 databases appear (not mock data)
-
Test functionality:
- List databases
- Create a test database
- View tables
- Execute queries
If your domain is in Cloudflare:
- Add route to wrangler.toml:
[[routes]]
pattern = "d1.yourdomain.com/*"
zone_name = "yourdomain.com"- Deploy:
wrangler deployCloudflare automatically creates the DNS record.
If using external DNS:
- Create CNAME record:
Type: CNAME
Name: d1
Value: your-worker-name.your-account.workers.dev
- Add route to wrangler.toml:
[[routes]]
pattern = "d1.yourdomain.com/*"
zone_name = "yourdomain.com"- Deploy:
wrangler deploySupport multiple domains in one deployment:
[[routes]]
pattern = "d1.yourdomain.com/*"
zone_name = "yourdomain.com"
[[routes]]
pattern = "database.example.com/*"
zone_name = "example.com"Create separate configs for different environments:
wrangler.production.toml:
name = "d1-manager-prod"
# ... production configwrangler.staging.toml:
name = "d1-manager-staging"
# ... staging configDeploy to specific environment:
# Staging
wrangler deploy --config wrangler.staging.toml
# Production
wrangler deploy --config wrangler.production.tomlSet secrets per environment:
# Staging secrets
wrangler secret put ACCOUNT_ID --config wrangler.staging.toml
# Production secrets
wrangler secret put ACCOUNT_ID --config wrangler.production.toml# Dry run (test without deploying)
wrangler deploy --dry-run
# Or deploy to workers.dev first
wrangler deploy --no-bundleUse git tags:
git tag -a v1.0.0 -m "Production release 1.0.0"
git push origin v1.0.0Update VERSION file:
echo "1.0.0" > VERSION
git commit -am "Bump version to 1.0.0"Enable observability:
[observability]
enabled = trueView logs:
wrangler tailWrangler keeps deployment history:
# List deployments
wrangler deployments list
# Rollback to previous
wrangler rollbackAutomate deployments with GitHub Actions:
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Workers
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "22"
- run: npm install
- run: npm run build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}View in Cloudflare Dashboard:
- Go to Workers & Pages
- Select your Worker
- Click Analytics
Metrics:
- Request count
- Error rate
- CPU time
- Duration (p50, p95, p99)
Tail logs in real-time:
wrangler tailFilter logs:
# Only errors
wrangler tail --status error
# Specific status codes
wrangler tail --status ok
# Search for text
wrangler tail --search "database"The Worker catches and logs errors:
// worker/index.ts
export default {
async fetch(request: Request, env: Env): Promise<Response> {
try {
return await handleApiRequest(request, env);
} catch (err) {
console.error("[Worker] Unhandled error:", err);
return new Response(
JSON.stringify({
error: "Internal Server Error",
}),
{ status: 500 },
);
}
},
};View errors in logs:
wrangler tail | grep ERRORMonitor authentication in Cloudflare Zero Trust:
- Go to Zero Trust β Logs β Access
- Filter by application name
- Review authentication events
Free Plan:
- 100,000 requests/day
- 10ms CPU time per request
- No D1 limits
Paid Plan ($5/month):
- Unlimited requests
- 50ms CPU time per request
- Pay-as-you-go for extra CPU
D1 Limits (as of 2024):
- 10GB storage per database
- 5GB reads/day (free)
- 100,000 writes/day (free)
- Enable Caching:
[assets.cache]
max_age = 31536000 # 1 year for static assets- Minimize Asset Size:
# Production build optimizations in vite.config.ts
build: {
minify: 'esbuild',
cssMinify: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom']
}
}
}
}- Use Connection Pooling:
D1 automatically handles connection pooling.
For high-traffic deployments:
- Monitor Quotas:
# Check D1 usage
wrangler d1 info d1-manager-metadata- Upgrade Plan if Needed:
Visit Cloudflare Dashboard β Account β Plans & Billing
- Implement Rate Limiting:
Add rate limiting in Worker if needed.
Add CSP headers in Worker:
// worker/utils/cors.ts
headers.set(
"Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';",
);Use minimal permissions:
- β Account β D1 β Edit
- β Not Global API Key
# Generate new API token
# Update secret
wrangler secret put API_KEYCloudflare Workers use HTTPS by default.
In Cloudflare Access, use specific rules:
Include: Email ends with @yourcompany.com
Exclude: Country is in [blocked countries]
Cause: Build errors or missing configuration
Solution:
# Check build
npm run build
# Validate wrangler.toml
wrangler validateCause: Not logged in to Wrangler
Solution:
wrangler logout
wrangler loginCause: D1 database not created or wrong ID
Solution:
# List databases
wrangler d1 list
# Verify database_id in wrangler.tomlCause: Missing or incorrect secrets
Solution:
# Verify secrets
wrangler secret list
# Re-set secrets
wrangler secret put ACCOUNT_ID
wrangler secret put API_KEYCause: Frontend still configured for local dev
Solution:
# Edit .env - comment out VITE_WORKER_API
# Rebuild and redeploy
npm run build
wrangler deploySee Authentication Setup troubleshooting section.
# 1. Pull latest changes
git pull origin main
# 2. Install dependencies
npm install
# 3. Build frontend
npm run build
# 4. Deploy
wrangler deployCloudflare Workers deployments are atomic:
- New version uploaded
- Traffic switches instantly
- No downtime
If something goes wrong:
# View deployment history
wrangler deployments list
# Rollback to previous version
wrangler rollbackFree Tier:
- Workers: 100,000 requests/day
- D1: 5GB reads, 100,000 writes/day
- Cost: $0
Paid Plan ($5/month):
- Workers: Unlimited requests, 10M CPU ms
- D1: Included storage, pay for additional I/O
- Cost: $5-10/month for typical usage
Free if domain is in Cloudflare (DNS only)
Free Tier:
- Up to 50 users
- Cost: $0
Teams Plan ($7/user/month):
- Unlimited users
- Advanced features
- Configuration - Advanced configuration options
- Authentication Setup - Set up Cloudflare Access
- Security Best Practices - Secure your deployment
- Monitoring - Monitor your production deployment
- Troubleshooting - Fix common issues
Need Help? See Troubleshooting or open an issue.
- Database Management
- R2 Backup Restore
- Scheduled Backups
- Table Operations
- Query Console
- Schema Designer
- Column Management
- Bulk Operations
- Job History
- Time Travel
- Read Replication
- Undo Rollback
- Foreign Key Visualizer
- ER Diagram
- Foreign Key Dependencies
- Foreign Key Navigation
- Circular Dependency Detector
- Cascade Impact Simulator
- AI Search
- FTS5 Full Text Search
- Cross Database Search
- Index Analyzer
- Database Comparison
- Database Optimization