Deployment Checklist Template
A copy-paste verification checklist for safe production deployments, from pre-merge tests to post-release monitoring.
Overview
A deployment checklist is a pre-release verification list that every release must clear before, during, and after it ships to production. Production deployments are high-risk moments: a single missed step can cause outages, data loss, or security exposures. This template gives every release the same verification path, from pre-merge testing through post-deployment monitoring, so quality stops depending on who happens to be deploying that day.
When to Use
Use this resource when:
- Preparing any deployment to production or staging
- Onboarding new team members to the release process
- Auditing the deployment process after an incident
- Defining go/no-go criteria for a new service or pipeline
Skip it for local development deploys and for flag-only rollouts with no infrastructure or schema changes, where a two-line sanity check is enough.
For the messaging side of a release, pair this checklist with the Rollout Communication Template.
Solution
# Deployment Checklist: `<Release Name>`
## Release Metadata
| Field | Value |
|-------|-------|
| Service | `name` |
| Version | `x.y.z` |
| Branch / Commit | `main@abc1234` |
| Deployer | `@username` |
| Date | `YYYY-MM-DD HH:MM UTC` |
| Ticket / PR | `PROJ-123` |
## 1. Pre-Deployment
### 1.1. Code & Tests
- [ ] All CI checks pass (lint, unit tests, integration tests)
- [ ] Code review approved by at least one senior engineer
- [ ] No unresolved security alerts (Snyk, Dependabot)
- [ ] Database migrations reviewed for backward compatibility
- [ ] Feature flags configured and defaulted to off
### 1.2. Infrastructure
- [ ] Staging environment deployed and validated
- [ ] Production capacity verified (CPU, memory, disk)
- [ ] Autoscaling rules reviewed (min / max replicas)
- [ ] Rollback artifact built and stored (Docker image, AMI)
- [ ] CDN cache invalidation plan documented (if applicable)
### 1.3. Communication
- [ ] Stakeholders notified of deployment window
- [ ] On-call engineer aware and available
- [ ] Status page updated to "Maintenance" (if downtime expected)
- [ ] Customer-facing teams briefed on changes
## 2. Deployment
### 2.1. Database (if applicable)
- [ ] Migration scripts tested against a copy of production data
- [ ] Migration run with `ALTER TABLE ... ADD COLUMN` (not destructive ops first)
- [ ] Migration duration estimated and approved by DBA
- [ ] Rollback script prepared for destructive changes
### 2.2. Application
- [ ] Deploy using blue/green or canary strategy
- [ ] Monitor error rate for 5 minutes after each canary increment
- [ ] Verify health checks return 200 OK
- [ ] Confirm new pods/containers are receiving traffic
### 2.3. Verification
- [ ] Smoke tests pass against production endpoints
- [ ] Critical user journeys tested (login, checkout, search)
- [ ] Logs show no unexpected errors or exceptions
- [ ] Metrics within baseline (latency p95, error rate, CPU)
## 3. Post-Deployment
### 3.1. Validation
- [ ] Feature flags enabled incrementally (5% → 25% → 100%)
- [ ] A/B test results monitored (if applicable)
- [ ] Customer support briefed on new capabilities or changes
- [ ] Documentation updated (API docs, runbooks, wiki)
### 3.2. Monitoring
- [ ] Dashboards checked for anomalies (traffic, errors, latency)
- [ ] Alerts firing as expected (no false positives or muted alerts)
- [ ] Synthetic monitoring passes (Pingdom, Datadog Synthetics)
- [ ] Error tracking reviewed (Sentry, Rollbar) for new issues
### 3.3. Cleanup
- [ ] Old versions scaled down after stability confirmed (30 min)
- [ ] Feature branches deleted
- [ ] Deployment log archived for audit
- [ ] Status page updated to "Operational"
Explanation
The checklist is ordered by risk: code quality first, then infrastructure readiness, then execution, then validation. The rollback artifact is a hard requirement because you can’t safely deploy what you can’t quickly undeploy — for strategies that keep rollback under a minute, see the zero-downtime deployment checklist. Canary increments with health checks catch issues before they affect all users, and post-deployment monitoring extends beyond the deploy moment because some issues (memory leaks, cache warming) only appear after sustained traffic.
The database section deserves its own discipline. Run schema changes with the expand-and-contract pattern: add the new columns or tables first, deploy the app version that tolerates both schemas, and only remove the old structures in a later release once nothing reads them. That keeps every individual deployment reversible — ship a destructive migration with the code that depends on it and the rollback path is gone.
Go/No-Go Criteria
A checklist item without a threshold is a debate waiting to happen. Attach a measurable gate to each stage so the decision is made by the numbers, not under pressure:
| Stage | Go signal | No-Go signal |
|---|---|---|
| CI | Lint, unit and integration tests green; zero unresolved critical alerts | Any red or flaky check, unreviewed migration |
| Staging | Smoke tests pass; metrics match baseline | p95 latency or error rate above baseline +10% |
| Canary | Error rate < 0.1% and p95 within baseline for 5-10 min | Error rate > 0.5% or repeated health check failures |
| Post-deploy | No new alerts in 30 min; synthetic checks green | New error-tracking issues above the hourly baseline |
Treat any No-Go as a rollback trigger, not a discussion point. The checklist exists to remove negotiation when the system is already telling you something is wrong.
Size the watch windows to the blast radius, not to the clock on the wall. A stateless API behind a feature flag can often ship with a 10-minute canary and a 30-minute post-deploy watch, while a release touching payments, auth, or schema changes earns a longer soak — an hour or more at each canary step, and someone explicitly assigned to watch dashboards instead of assuming alerts will page. Write the window into the checklist before the deploy starts; deciding “a bit longer” mid-release is how a 15-minute watch quietly becomes zero minutes.
Canary Deployment Script
The script below automates sections 2.2 and 2.3 for a Kubernetes setup using an Istio VirtualService to shift traffic. It requires BUILD_TAG (the image tag being released) and rolls back automatically if the canary error rate crosses 1% or the metrics endpoint can’t be read.
#!/bin/bash
# Canary deployment with health checks (Kubernetes + Istio VirtualService)
set -euo pipefail
SERVICE="api"
NAMESPACE="production"
CANARY_PERCENT=10
BUILD_TAG="${BUILD_TAG:?required — set to the image tag you are releasing}"
echo "=== Canary Deployment: $SERVICE ==="
# Step 1: Deploy canary
echo "[1/5] Deploying canary pod..."
kubectl set image "deployment/$SERVICE-canary" "$SERVICE=registry.example.com/$SERVICE:$BUILD_TAG" -n "$NAMESPACE"
kubectl rollout status "deployment/$SERVICE-canary" -n "$NAMESPACE" --timeout=120s
# Step 2: Route 10% traffic to canary
echo "[2/5] Routing $CANARY_PERCENT% traffic to canary..."
kubectl patch virtualservice "$SERVICE" -n "$NAMESPACE" --type merge -p '{"spec":{"http":[{"route":[{"destination":{"host":"'"$SERVICE"'","subset":"stable"},"weight":90},{"destination":{"host":"'"$SERVICE"'","subset":"canary"},"weight":'"$CANARY_PERCENT"'}]}]}}'
# Step 3: Monitor for 10 minutes
echo "[3/5] Monitoring canary for 10 minutes..."
sleep 600
# Empty result is treated as a failure: unknown health is not healthy
ERROR_RATE=$(kubectl exec -n "$NAMESPACE" "deployment/$SERVICE-canary" -- curl -s http://localhost:8080/metrics | grep error_rate | awk '{print $2}' || true)
ERROR_RATE="${ERROR_RATE:-1}"
echo " Error rate: $ERROR_RATE"
if (( $(echo "$ERROR_RATE > 0.01" | bc -l) )); then
echo " ERROR: Error rate too high, rolling back canary"
kubectl patch virtualservice "$SERVICE" -n "$NAMESPACE" --type merge -p '{"spec":{"http":[{"route":[{"destination":{"host":"'"$SERVICE"'","subset":"stable"},"weight":100}]}]}}'
kubectl delete "deployment/$SERVICE-canary" -n "$NAMESPACE"
exit 1
fi
# Step 4: Promote to full rollout
echo "[4/5] Promoting canary to full rollout..."
kubectl set image "deployment/$SERVICE" "$SERVICE=registry.example.com/$SERVICE:$BUILD_TAG" -n "$NAMESPACE"
kubectl rollout status "deployment/$SERVICE" -n "$NAMESPACE" --timeout=300s
# Step 5: Clean up canary
echo "[5/5] Cleaning up canary resources..."
kubectl patch virtualservice "$SERVICE" -n "$NAMESPACE" --type merge -p '{"spec":{"http":[{"route":[{"destination":{"host":"'"$SERVICE"'","subset":"stable"},"weight":100}]}]}}'
kubectl delete "deployment/$SERVICE-canary" -n "$NAMESPACE"
echo "=== Canary Deployment Complete ==="
If you don’t run Istio, swap the virtualservice patches for your ingress controller’s canary annotations or a service mesh of your choice — the deploy → route → measure → promote shape stays the same.
Deployment Communication Template
=== Deployment Communication ===
Channel: #deployments
Deployer: alice@example.com
Date: 2026-07-11 14:00 UTC
Starting deployment: API v2.3.1
Risk level: MEDIUM
Changes: Bug fixes + performance improvements
Rollback: git revert + redeploy (est. 5 min)
14:00 - Deploying to staging... DONE
14:05 - Smoke tests in staging... PASS
14:10 - Deploying canary (10% traffic)...
14:20 - Canary metrics look good (error rate: 0.02%)
14:25 - Promoting to full rollout...
14:30 - Rollout complete. Monitoring for 30 min.
15:00 - Deployment confirmed stable. Status: OPERATIONAL.
If issues detected: contact #on-call, reference CHG-2026-07-11-001
Rollback command: ./scripts/rollback.sh API v2.3.0
Variants
| Context | Approach | Notes |
|---|---|---|
| Hotfix | Abbreviated checklist | Skip non-critical steps, focus on tests and rollback |
| Scheduled maintenance | Extended communication section | Include maintenance window, customer notifications |
| Database-only change | Database section emphasized | Require DBA sign-off, longer soak period |
| First deploy of a new service | Full checklist plus infrastructure review | Add DNS, TLS, and runbook checks before go-live |
Filled Example
This is what the checklist looks like filled in for a real release — api-billing v2.4.0, which ships a schema migration behind a feature flag:
# Deployment Checklist: api-billing v2.4.0
| Field | Value |
|-------|-------|
| Service | api-billing |
| Version | 2.4.0 |
| Branch / Commit | main@f31c9d2 |
| Deployer | @mpaulenko |
| Date | 2026-10-16 14:00 UTC |
| Ticket / PR | BILL-882 |
## Pre-Deployment
- [x] CI green on PR #412, approved by two senior engineers
- [x] Migration `20261015_add_refund_reason.sql` tested on a production copy (12 min)
- [x] Rollback image `api-billing:2.3.9` tagged in the registry
- [x] Feature flag `refund_v2` configured, defaulted off
- [x] #deployments channel notified, on-call engineer confirmed
## Deployment
- [x] Migration ran in 11 min — expand only, no drops
- [x] Canary at 10% for 10 min: error rate 0.02%, p95 180ms (baseline 172ms)
- [x] Full rollout completed at 14:35 UTC
## Post-Deployment
- [x] `refund_v2` enabled 5% → 25% → 100% over 2 hours
- [x] No new Sentry issues during the 30-minute watch window
- [x] Old pods scaled to 0 at 15:10 UTC
- [ ] Checklist review scheduled after next incident review
Two details in the filled version matter more than the checkmarks themselves. The migration is logged with its measured duration — next time someone estimates a similar change they get a real number, not a guess. And the watch window has a nameless but explicit owner: someone wrote down that the pods went to zero at 15:10, which means the cleanup step actually ran instead of being assumed. Deployments rot from vague confirmations faster than from missing steps.
The blank template, this filled example, and the canary script are published as files in the companion repository — copy them straight into your wiki or repo.
Adapting the Checklist to Your Pipeline
The checklist works as a document, but every item that can be automated should become a pipeline gate instead of a manual checkbox:
| Checklist section | Pipeline gate |
|---|---|
| Code & Tests | Required status checks plus a security scan job |
| Infrastructure | Staging deploy job followed by a capacity smoke test |
| Database | Manual approval step with the migration diff attached |
| Canary | Progressive delivery controller (Argo Rollouts, Flagger) |
| Post-deploy monitoring | Automated metric analysis or a timed hold before promote |
Argo Rollouts and Flagger codify exactly the canary → analysis → promote loop from section 2.2, and both can abort a rollout automatically when metrics regress. Keep manual approval steps where judgment matters — stakeholder notice, business sign-off, a second pair of eyes — and automate everything mechanical. For a worked example of the surrounding pipeline, see the CI/CD with GitHub Actions guide.
Store the checklist itself next to the pipeline as code — a YAML file or a markdown doc in the repo — so every change goes through the same review as the application. Automation has a floor, though: a team shipping once a month gets more from a sharp one-page checklist than from a progressive-delivery controller the team has to run. Adopt the tooling when deploy frequency and failure cost justify running it, not before.
What Works
- Automate every checkbox that can be automated (tests, smoke tests, health checks)
- Run the checklist in a shared document or tool so a second person can confirm the steps
- Never deploy on Friday afternoons or before holidays unless it’s a critical fix
- Keep the checklist short enough to complete in 15 minutes for routine deployments
- Review and update the checklist after every incident that involved a deployment
Common Mistakes
- Skipping staging validation because “the change is small”
- Deploying without a tested rollback plan — or with a rollback plan nobody has ever run
- Shipping a destructive migration in the same release as the code that depends on it
- Not monitoring after the deploy is “complete”; memory leaks show up under sustained load
- Deploying several unrelated changes in the same release, making rollback all-or-nothing
- Allowing deployers to work alone without a second pair of eyes
Troubleshooting
- Pipeline fails silently: enable verbose logging and store pipeline artifacts between stages so you can inspect the exact state that failed.
- Container crashes on startup: check that environment variables, secrets, and config files are mounted correctly. Read the first 50 lines of logs before scaling replicas.
- Deployment rolls back repeatedly: verify health checks, resource limits, and startup probes. A failing readiness probe is a common cause of rolling restarts.
- Slow CI builds: cache dependencies and Docker layers. Split large test suites into parallel jobs to reduce wall-clock time.
- Drift between environments: use infrastructure-as-code and immutable artifacts so staging actually predicts production.
Further Reading
- Kubernetes docs — kubectl rollout: the rollout commands the canary script builds on.
- Istio docs — Traffic Shifting: weighted routing used for canary increments.
- Argo Rollouts documentation: automating the canary → analysis → promote loop.
- Martin Fowler — Evolutionary Database Design: the expand-and-contract approach behind the migration section.
Frequently Asked Questions
Should every deployment use this full checklist?
No. For routine deployments with no infrastructure changes, a shortened checklist (tests, deploy, smoke tests, monitor) is sufficient. Use the full checklist for releases with database changes, new dependencies, or architectural modifications.
Who should own the checklist?
The on-call engineer or release lead owns the checklist for a specific deployment. The platform or SRE team owns the template itself and updates it based on incident lessons.
How do I handle emergency hotfixes?
Use an abbreviated checklist: verify the fix in staging, build the artifact, deploy with a canary, run smoke tests, monitor for 15 minutes. Document the emergency deploy in a post-incident review to determine if process gaps caused the urgency.
How do we handle database migrations during deployment?
Run migrations before the application deploy using expand-and-contract: add the new columns or tables, deploy the version that works with both schemas, and drop the old structures in a later release. Never ship destructive changes in the same deployment as the code that depends on them — that's when rollback stops being an option. Test every migration on a production copy, write the rollback migration up front, and set a time limit: if a rollback can't finish inside 15 minutes, escalate to restoring from backup instead of improvising under pressure.
What is blue-green deployment and when should we use it?
Blue-green deployment keeps two identical environments: blue (current) and green (new). You deploy the new version to green, run tests, then switch traffic from blue to green. Use it when you need zero downtime and instant rollback, and you can afford two environments. Avoid it for database-heavy changes (both environments share the database), cost-sensitive workloads, or infrastructure too complex to duplicate.
How do we manage deployments during peak traffic?
Avoid deploying during peak hours and define low-traffic windows instead — typically 10:00-14:00 UTC on weekdays for global services, or early morning local time for regional ones. If a deploy is genuinely urgent during peak, use a canary at a very small percentage (1-5%) with longer monitoring windows and extra on-call coverage. Tell stakeholders it's happening and why, then document the decision in the post-deployment review.
What is feature flag deployment and how does it differ from canary?
Feature flags decouple deployment from release: you ship the code to every instance but keep the feature disabled, then enable it gradually (0% → 100%) without redeploying. Canary routes a percentage of traffic to new instances running the new version. Flags are better for gradual feature rollout, A/B testing, and instant disable; canary is better for validating infrastructure changes and runtime behavior under real load.
How do we automate the deployment checklist?
Turn the checklist into a CI/CD pipeline with gates: automated tests, security scans, staging deploy, smoke tests, canary with metric analysis, and a production rollout step. Tools like Argo Rollouts and Flagger automate the progression; steps that need judgment (stakeholder notification, business sign-off) stay as manual approval gates. Version the checklist as code next to the pipeline so changes go through review like everything else.
How do we manage deployment dependencies between services?
Keep service dependencies documented in a catalog and check them before deploying: if downstream consumers depend on the current API contract, a breaking change needs coordination, a feature flag, or a versioned endpoint. Deploy in dependency order — infrastructure, databases, backend, then frontend — and use contract testing (Pact) in CI to catch incompatibilities before the release window.
Related Resources
Post-Deployment Verification Checklist Template
A checklist template for verifying deployments: health checks, smoke tests, metric validation, and rollback readiness before declaring all-clear.
DocZero-Downtime Deployment Checklist
A checklist to ensure production deployments complete without service interruptions using safe rollout patterns.
DocDeployment Rollback Runbook
Runbook for rolling back failed deployments: triggers, kubectl/Helm/ArgoCD commands, database migration rollback, and verification checklists.
DocRollout Communication Template
A template for release notes and stakeholder updates during capability rollouts.
RecipeDocker Health Check Configuration for Container Reliability
Add proper health checks to Docker containers with HEALTHCHECK
GuideComplete Guide to CI/CD with GitHub Actions
Build CI/CD pipelines from scratch with GitHub Actions. Covers workflows, runners, matrix builds, caching, secrets, environments, deployment strategies, and reusable workflows.