Safe Rollback Strategies
The worst rollback I witnessed wasn't slow — it was impossible. We deployed API v2.4 with a migration that dropped a column v2.3 still read. Someone hit rollout undo. Pods crashed in CrashLoopBackOff because old code met new schema. We spent forty minutes restoring from snapshot while checkout stayed down.
Safe rollback is designed before deploy day: immutable artifacts, reversible schema changes, and a decision tree the on-call can follow without opening Confluence.
Rollback layers
| Layer | Mechanism | Speed | Reversibility |
|---|---|---|---|
| Feature flag | Disable flag | Seconds | Full |
| Traffic | LB/mesh weight to old version | Seconds–minutes | Full if old stack exists |
| App | Rollout undo / redeploy previous image | 1–5 minutes | Full if schema compatible |
| Database | Restore snapshot / reverse migration | 15–60+ minutes | Partial, data loss risk |
| Infrastructure | Terraform state revert | Minutes–hours | Depends on destruction |
Fastest rollback is the feature flag kill switch. Slowest is database restore. Design so you rarely descend past app rollback.
Immutable artifacts
Tag container images with Git SHA, not latest. Rollback means redeploying api:abc123f, which still exists in the registry.
# Deployment — pin digest or SHA tag
spec:
containers:
- name: api
image: registry.acme.com/api:abc123f
If your registry GC deletes untagged images after 30 days, rollbacks beyond that window break. Retain release tags permanently or mirror to a release artifact store.
Helm charts: version chart + image together. helm rollback release 47 only works if chart 47's image tag is still pullable.
Application rollback runbook
Kubernetes (imperative emergency):
kubectl rollout undo deployment/api -n production
kubectl rollout status deployment/api -n production
GitOps (preferred):
git revert HEAD --no-edit
git push origin main
# Argo CD syncs automatically or:
argocd app sync api-production
Verify rollback with synthetic checks, not just pod readiness:
curl -sf https://api.acme.com/health/deep | jq .
# Run smoke test suite against production (read-only tests)
Document expected rollback time in the runbook. If undo takes 5 minutes but your SLA is 99.95%, you need canary or flags to cut blast radius earlier.
Database: assume you can't roll back
Forward-only migrations with expand-contract (see zero-downtime migrations post). Emergency schema rollback via snapshot:
- Stop writes (maintenance mode or read-only flag)
- Restore DB snapshot to point-in-time before migration
- Replay WAL/binlog if needed (Postgres PITR, RDS restore)
- Redeploy old app
Data loss window = time between migration and rollback decision. For high-traffic systems, PITR is the only option; flyway undo scripts rarely get tested.
Keep migration PRs labeled expand, migrate, contract so on-call knows whether app rollback is safe without schema rollback.
Blue-green and canary simplify app rollback
Blue-green: flip traffic to blue stack. Canary: set canary weight to 0. Both require the old version still running — don't scale primary to zero immediately after promotion.
We keep n-1 deployment at minimum replicas for 24 hours post-release. Cost is small; rollback is instant.
Roll-forward vs roll-back decision tree
Incident detected
│
├─ Feature flag exists? ──YES──► Disable flag (stop here if fixed)
│
NO
│
├─ Schema backward compatible? ──NO──► Can you roll forward fix in <15 min?
│ │
YES YES ──► Hotfix deploy
│ NO ──► PITR + comms (major incident)
│
└─ kubectl rollout undo / Git revert
│
└─ Smoke tests pass? ──NO──► Escalate, consider PITR
Post every rollback incident: was the rollback path tested in staging this quarter? If not, add it to the next game day.
Testing rollbacks in CI
Quarterly automated test:
- Deploy version A to staging
- Deploy version B with migration
- Execute rollback procedure
- Assert version A passes integration suite against post-migration schema (or confirm migration was expand-only)
This catches the CrashLoop scenario before prod.
Communicating during rollback
Rollback procedure includes customer communication templates staged in advance: status page update draft, support macro, executive summary slot. During incidents, writing copy from scratch burns minutes.
Record rollback decisions in the incident timeline — "rolled back to SHA xyz at 14:24 UTC" — even when rollback is automated. Post-incident review needs human intent, not just Argo CD sync logs.
Practice rollback quarterly on staging with production-like data volume. Teams that only rollback in prod discover broken rollback scripts when it matters most.
Common production mistakes
Teams get rollback strategies safe wrong in predictable ways:
- Skipping failure-mode rehearsal — run a game day or fault injection exercise before peak traffic, not after the first outage.
- Missing correlation context — every error path should carry request, trace, or tenant identifiers so incidents are debuggable.
- Optimizing for demo, not steady state — load tests, cache warm-up, and cold-start paths matter more than local dev latency.
- Undocumented trade-offs — if you chose speed over strict correctness (or vice versa), write that down for the next engineer.
Production implementations of rollback strategies safe fail when staging mirrors production topology poorly, rollback is untested, and on-call runbooks describe the happy path only.
Debugging and triage workflow
When rollback strategies safe misbehaves in production, work top-down instead of guessing:
- Confirm scope — one tenant, region, or deployment stage? Narrow blast radius before deep diving.
- Check recent changes — deploys, flag flips, config pushes, and schema migrations in the last 24 hours.
- Compare golden signals — latency, error rate, saturation, and traffic for the affected surface vs. baseline.
- Reproduce minimally — smallest input or scenario that triggers the failure; capture traces/logs with correlation IDs.
- Fix forward or rollback — if rollback is faster than root-cause during incident, rollback first, postmortem second.
- Add a guard — alert, integration test, or circuit breaker so the same class of failure is caught earlier next time.
Document the timeline during triage. Future you (and on-call) will need timestamps, not just conclusions.
Resources
- Kubernetes rollout undo documentation
- Argo CD rollback guide
- AWS RDS point-in-time recovery
- Google SRE — managing incidents
- Flyway undo limitations
Frequently asked questions
What is the fastest safe rollback for a Kubernetes deployment?
kubectl rollout undo deployment/name reverts to the previous ReplicaSet — typically under 60 seconds if images are cached. For GitOps-managed clusters, revert the Git commit and sync rather than kubectl patch, or you'll fight the controller on the next sync.
Can you always roll back database migrations with the application?
No. Destructive migrations (dropped columns, data transforms) can't be reversed by rolling back app code alone. Use expand-contract migrations so app rollback is always possible without schema rollback.
When should you roll forward instead of rolling back?
When the bug is minor, rollback risk exceeds fix risk (schema already migrated forward-only), or the previous version has a known security vulnerability. Roll-forward with a hotfix commit is often safer than yanking a release that's half-deployed.
Hiring a senior Android / Flutter engineer?
I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.
Get in touch →