| name | Deployment Strategies |
| description | This skill should be used when the user asks about "deployment", "CI/CD", "continuous integration", "GitHub Actions", "GitLab CI", "environments", "staging", "production", "rollback", "versioning", "gradual rollout", "canary deployment", "blue-green deployment", or discusses deploying Workers, managing multiple environments, or setting up automated deployment pipelines. |
| version | 0.1.0 |
Deployment Strategies
Purpose
This skill provides guidance on deploying Cloudflare Workers, managing multiple environments, implementing CI/CD pipelines, and using deployment best practices. Use this skill when setting up deployment workflows, managing staging and production environments, implementing rollback strategies, or integrating with CI/CD systems.
Environment Management
Multi-Environment Configuration
Use wrangler.jsonc environments for staging/production separation:
{
"name": "my-worker",
"main": "src/index.ts",
"vars": {
"ENVIRONMENT": "production"
},
"kv_namespaces": [
{ "binding": "CACHE", "id": "prod-kv-id" }
],
"env": {
"staging": {
"vars": { "ENVIRONMENT": "staging" },
"kv_namespaces": [
{ "binding": "CACHE", "id": "staging-kv-id" }
]
},
"development": {
"vars": { "ENVIRONMENT": "development" },
"kv_namespaces": [
{ "binding": "CACHE", "id": "dev-kv-id" }
]
}
}
}
Deploy to specific environment:
wrangler deploy --env staging
wrangler deploy --env production
Best Practices
- Separate resources: Use different KV namespaces, D1 databases, R2 buckets per environment
- Environment variables: Use
ENVIRONMENT var to conditionally enable features
- Secrets per environment:
wrangler secret put API_KEY --env staging
- Test in staging: Always deploy to staging before production
- Monitor after deploy: Use
wrangler tail --env production after deployment
CI/CD Integration
GitHub Actions
.github/workflows/deploy.yml:
name: Deploy Worker
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Deploy to staging
if: github.event_name == 'pull_request'
uses: cloudflare/wrangler-action@v3
with:
apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env staging
- name: Deploy to production
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: cloudflare/wrangler-action@v3
with:
apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env production
Setup:
- Add
CLOUDFLARE_API_TOKEN to GitHub Secrets
- Get token from Cloudflare Dashboard → My Profile → API Tokens
- Create token with "Edit Cloudflare Workers" permissions
GitLab CI
.gitlab-ci.yml:
stages:
- test
- deploy
variables:
NODE_VERSION: "20"
test:
stage: test
image: node:\${NODE_VERSION}
script:
- npm ci
- npm test
deploy_staging:
stage: deploy
image: node:\${NODE_VERSION}
only:
- merge_requests
script:
- npm ci
- npx wrangler deploy --env staging
variables:
CLOUDFLARE_API_TOKEN: \$CLOUDFLARE_API_TOKEN
deploy_production:
stage: deploy
image: node:\${NODE_VERSION}
only:
- main
script:
- npm ci
- npx wrangler deploy --env production
variables:
CLOUDFLARE_API_TOKEN: \$CLOUDFLARE_API_TOKEN
Deployment Workflows
Pre-Deployment Checklist
npm test
npm run build
wrangler deploy --dry-run --env production
wrangler d1 migrations list DB --remote
wrangler deploy --env staging
curl https://staging.example.com/health
wrangler deploy --env production
wrangler tail --env production
Post-Deployment
wrangler tail --env production
wrangler tail --env production --status error
curl https://production.example.com/health
wrangler deployments list
Rollback Strategies
Quick Rollback
wrangler deployments list
wrangler rollback <deployment-id>
wrangler deployments list
Version Pinning
export default {
async fetch(request, env) {
const response = await handleRequest(request, env);
response.headers.set('X-Worker-Version', env.VERSION || 'unknown');
return response;
}
};
Set version in wrangler.jsonc:
{
"vars": {
"VERSION": "1.2.3"
}
}
Canary Deployments
Not natively supported; use percentage-based routing:
export default {
async fetch(request, env) {
const random = Math.random();
if (random < 0.1) {
return await newVersionHandler(request, env);
}
return await stableVersionHandler(request, env);
}
};
Database Migrations
D1 Migration Workflow
wrangler d1 migrations create DB add_users_table
wrangler d1 migrations apply DB
wrangler dev
wrangler d1 migrations apply DB --env staging --remote
wrangler d1 migrations apply DB --env production --remote
wrangler deploy --env production
Important: Always apply migrations before deploying Worker code that depends on them.
Secrets Management
Deployment Secrets
wrangler secret put API_KEY --env staging
wrangler secret put API_KEY --env production
wrangler secret put DATABASE_URL --env staging
wrangler secret put DATABASE_URL --env production
wrangler secret list --env production
Secret Rotation
wrangler secret put API_KEY_NEW --env production
wrangler deploy --env production
wrangler secret delete API_KEY --env production
Monitoring and Observability
Real-Time Monitoring
wrangler tail --env production
wrangler tail --env production --status error
wrangler tail --env production --method POST
wrangler tail --env production --search "user-id-123"
Health Checks
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === '/health') {
try {
await env.DB.prepare('SELECT 1').first();
await env.CACHE.get('health-check');
return new Response(JSON.stringify({
status: 'healthy',
version: env.VERSION,
environment: env.ENVIRONMENT
}), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response(JSON.stringify({
status: 'unhealthy',
error: error.message
}), {
status: 503,
headers: { 'Content-Type': 'application/json' }
});
}
}
return await handleRequest(request, env);
}
};
Best Practices
- Always test in staging before production
- Use semantic versioning for releases
- Automate deployments with CI/CD
- Monitor after every deployment
- Have rollback plan ready
- Apply database migrations before code
- Use environment-specific resources
- Keep secrets out of code (use wrangler secret)
- Tag releases in git for tracking
- Document deployment process
Troubleshooting
Issue: "Deployment failed - binding not found"
- Solution: Ensure all bindings (KV, D1, R2) are created and IDs match wrangler.jsonc
Issue: "Migration failed"
- Solution: Check SQL syntax, ensure migrations run in order, verify database exists
Issue: "Secrets not working after deployment"
- Solution: Re-set secrets after creating new environment:
wrangler secret put KEY --env ENV
Issue: "Changes not reflecting"
- Solution: Clear browser cache, check deployment logs, verify correct environment deployed
For the latest deployment documentation, use the cloudflare-docs-specialist agent.