24.13. Rollback Strategies
Table of Contents
Why Rollback Strategies Matter
In CI/CD, deployments are frequent and automated. Eventually, a deployment will break something. A rollback strategy is your safety net, a clear and tested way to get your system back to a healthy state fast.
Without a rollback strategy you might:
- Leave users on a broken version for a long time.
- Panic and manually change things on the server.
- Introduce even more bugs during the chaos.
With a rollback strategy you:
- Know what to do, how, and who is responsible.
- Can integrate rollbacks into your CI/CD pipeline.
- Reduce downtime and stress.
A deployment without a rollback strategy is not a safe deployment.
This chapter explains the main rollback strategies, when to use them, and how they relate to CI/CD pipelines.
Concepts: Rollback vs Roll-Forward
Before looking at specific strategies you need two core ideas.
Rollback
A rollback means returning your system to a previous known good version.
Examples:
- Redeploying Docker image
app:1.4.0becauseapp:1.5.0is broken. - Switching the active Kubernetes deployment from
v3back tov2. - Restoring a database from a backup taken before a bad migration.
Characteristics:
- You go back in time to a stable version.
- Fast when it is automated and preconfigured.
- Might lose some new data if the database schema changed.
Roll-Forward
A roll-forward means deploying a new fix that corrects the problem in the latest version.
Examples:
- Hotfix branch
hotfix/payment-bugmerged and deployed asapp:1.5.1. - Quick database migration that fixes a bad column value.
Characteristics:
- You keep the new release, but repair it.
- Usually slower than a prepared rollback.
- Useful for small, well-understood bugs.
In CI/CD you usually:
- Rollback quickly to restore service.
- Then roll-forward with a fix after proper testing.
Simple Rollback: Redeploy Previous Version
The simplest rollback is to redeploy the last working build.
Requirements
To do this safely your pipeline must:
- Keep a history of artifacts (Docker images, JARs, zip files).
- Store a deployment manifest that says which version is currently in production.
- Have an automated step that can redeploy any of the last N versions.
Example of versioned Docker images:
| Version | Docker Tag | Status |
|---|---|---|
| 1.4.0 | app:1.4.0 | Stable |
| 1.5.0 | app:1.5.0 | Broken |
| latest | app:latest | Points to 1.5.0 |
If 1.5.0 is broken, you run:
docker service update \
--image my-registry.com/app:1.4.0 \
my-app-serviceIn Kubernetes, you might change the image tag in your deployment manifest and apply it again.
Integrating with CI/CD
In a simple CI/CD pipeline:
- Build stage:
- Build artifact.
- Tag with version (git commit hash, tag, or build number).
- Push artifact to registry.
- Deploy stage:
- Deploy the latest version by default.
- Tag deployment with the version.
- Rollback stage (manual job in the pipeline):
- Read the previous stable version from a metadata store.
- Redeploy that version automatically.
Pipeline example (pseudo YAML):
jobs:
deploy_prod:
steps:
- name: Deploy current version
run: ./deploy.sh $CI_COMMIT_SHA
rollback_prod:
when: manual
steps:
- name: Get last stable version
run: ./get_last_stable.sh > version.txt
- name: Deploy last stable version
run: ./deploy.sh $(cat version.txt)Pros and Cons
| Pros | Cons |
|---|---|
| Simple to understand and implement | May not handle DB schema changes well |
| Works with many hosting environments | Users might lose access to new features |
| Easy to automate in CI/CD | Data shape must remain backward compatible |
For simple redeploy rollbacks, always keep at least one previous artifact and track which version is stable.
Database-Aware Rollbacks
Code rollbacks are usually quick. Database rollbacks are trickier.
When you deploy a new version, you often apply migrations that change the database schema. For example:
ALTER TABLE users ADD COLUMN phone_number TEXT;If you later roll back the code, you must ensure the database schema and data are still compatible.
Forward-Only Migrations vs Down Migrations
With migration tools like Alembic, Liquibase, or Flyway you can:
- Apply up/forward migrations to move to a newer schema.
- Apply down migrations to revert to an older schema.
But not all changes are easy to roll back. For example:
ALTER TABLE orders DROP COLUMN notes;If you drop a column, you lose the data, and a down migration cannot magically restore it.
Because of this, many teams practice forward-only migrations:
- Schema moves forward only.
- Rollback of code must be compatible with the latest schema.
Designing Backward-Compatible Changes
To make rollbacks safe, design database changes that are backward compatible with the previous code version.
Common patterns:
- Add, then use, then remove:
- Deployment 1: Add new column
new_price, keep oldprice. - Deployment 2: Start writing to both
priceandnew_price. - Deployment 3: Read from
new_priceonly. - Deployment 4: Drop old
price. - Soft changes before hard changes:
- Add constraints, but do not enforce strictly at first.
- Clean data.
- Enforce constraints later.
- Avoid destructive changes during risky features:
- Do not drop tables or columns in the same release that introduces complex feature changes.
Database Backups as a Rollback Option
In serious failures, you might need to restore from backup.
Typical sequence:
- Deployment runs a wrong migration that deletes important data.
- Application breaks, or data is corrupted.
- Incident response:
- Stop write traffic (maybe switch to maintenance mode).
- Restore database from a backup taken just before the migration.
- Redeploy the last stable application version.
Restoring from backup can be slow and might lose recent data, so it is a last resort rollback.
Never rely only on backups for routine rollbacks. Use backups for disaster recovery, not for normal feature rollbacks.
Canary Releases and Progressive Rollback
A canary release means you deploy the new version to a small part of traffic first.
If it behaves well, you gradually increase the percentage of traffic. If it fails, you roll back to the previous version before everyone is affected.
Example Traffic Progression
| Step | New Version Traffic | Old Version Traffic |
|---|---|---|
| 1 | 5% | 95% |
| 2 | 25% | 75% |
| 3 | 50% | 50% |
| 4 | 100% | 0% |
If error rates spike at step 2, you can immediately send traffic back to the old version.
CI/CD Integration
A typical canary pipeline:
- Deploy new version as a separate instance (or set of instances).
- Update routing (load balancer or service mesh) to send 5 percent traffic to new version.
- Monitor metrics and logs for a defined time, for example 15 minutes.
- If OK, increase to 25 percent, then 50 percent, then 100 percent.
- If not OK at any step:
- Send traffic back to 0 percent new version.
- Mark deployment as failed.
You can automate this with:
- Kubernetes + service mesh (e.g. Istio, Linkerd).
- Cloud providers (e.g. AWS App Mesh, GCP traffic splitting).
- Feature flags for some use cases.
Rollback in Canary
Rollback here is mainly about traffic routing:
- If failure is detected at step 2, rollback = change routing rules to 0 percent new version, 100 percent old version.
- Then optionally delete the new version pods or instances.
This is usually faster and safer than redeploying code since both versions are already running.
Blue-Green Deployments and Instant Rollback
A blue-green deployment keeps two full environments:
- Blue: current production.
- Green: new version, prepared but not yet public.
At any time, traffic flows to exactly one environment.
How It Works
- Blue environment runs version 1.4.0.
- CI/CD pipeline deploys version 1.5.0 to Green environment.
- You run tests and health checks against Green.
- When ready, switch traffic from Blue to Green.
- If there is a problem:
- Switch traffic back from Green to Blue.
Traffic switching happens at route level:
- Load balancer DNS or reverse proxy config.
- Kubernetes Ingress or service definitions.
Rollback with Blue-Green
Rollback is simply:
- Change traffic back to the previous environment.
The old version is still running and ready. This makes rollback instant.
Example using DNS or load balancer:
| State | api.example.com Points To |
|---|---|
| Before deployment | Blue environment |
| After successful test | Green environment |
| After failure | Back to Blue environment |
Considerations
Blue-green is very powerful, but:
- Needs double infrastructure capacity.
- Requires careful DB migration handling (often combined with backward-compatible schema changes).
- Needs good automation for switching environments.
In blue-green deployment, never perform destructive DB changes that only work with the new version. Design migrations to keep both blue and green versions working during the switch.
Feature Flags as a Logical Rollback
Feature flags (also called feature toggles) allow you to enable or disable specific code paths without redeploying.
Instead of rolling back the whole application, you can turn off just the failing feature.
Basic Idea
In code:
if is_feature_enabled("new_checkout"):
run_new_checkout()
else:
run_old_checkout()Configuration system:
- Stores flags like
new_checkout = true/false. - Can change flags at runtime.
- Sometimes supports percentage rollout, user segments, etc.
Rollback with Feature Flags
Timeline:
- You deploy version 1.5.0, which contains new checkout code guarded by flag
new_checkout. - Initially,
new_checkout = false, so only old checkout runs. - You slowly turn
new_checkoutto true for, say, 10 percent of users. - If you detect problems with new checkout:
- Set
new_checkout = false. - All users return to old checkout behavior without changing code.
In many systems, feature flags are updated instantly via:
- Config service.
- Remote feature management tool (e.g. LaunchDarkly, Unleash, homegrown solution).
This is a logical rollback:
- Same code runs on servers.
- Behavior changes based on dynamic configuration.
Combining Feature Flags with CI/CD
In CI/CD pipelines:
- Deployment does not automatically enable all features.
- After deploy, you or an automated system:
- Turn on flags gradually.
- Monitor metrics.
- Roll flags back if needed.
This reduces the need to roll back entire releases, because you can limit problematic features quickly.
Automatic vs Manual Rollbacks
Not every rollback should be fully automatic, but some can be.
Automatic Rollbacks
An automatic rollback triggers based on objective signals:
- Health checks failing repeatedly.
- Error rate above a threshold.
- Latency above a threshold.
- Deployment step failing.
Example rule:
- If 5xx error rate stays above 5 percent for more than 5 minutes after deployment, rollback the deployment automatically.
In CI/CD this can be integrated with:
- Monitoring tools (Prometheus, Datadog, etc.).
- Alerting systems that call deployment tools or pipelines.
- Built-in cloud deployment controllers.
Manual Rollbacks
Manual rollbacks are triggered by a human:
- For complex situations where automated rules might be wrong.
- When the impact is not clear.
- When multiple systems are involved and need coordination.
Best practice is to:
- Automate the rollback action, but trigger it manually for tricky releases.
Example:
rollback_prodjob in your CI/CD pipeline that an engineer starts with one click.- The job itself performs the steps safely and consistently.
Humans should decide when to roll back, but scripts and tools should execute the rollback. Avoid manual server changes during incidents.
Versioning and Traceability
Rollback strategies only work if you know exactly what you are rolling back to.
You need:
- Versioned artifacts:
- Docker tags, JAR versions, or similar.
- Immutable builds:
- You never rebuild
app:1.4.0. It is always the same bits. - Deployment records:
- When was version X deployed?
- By which pipeline or person?
- To which environment?
Example deployment record table:
| Environment | Current Version | Previous Version | Deployed At |
|---|---|---|---|
| staging | a1b2c3d | 789abcd | 2026-08-28 10:15 UTC |
| prod | 789abcd | 1234567 | 2026-08-28 09:00 UTC |
If production breaks, you immediately see that rolling back means deploying 1234567.
Choosing a Rollback Strategy
You rarely use only one strategy. Typically you combine several:
| Context | Good Strategy Combination |
|---|---|
| Small app, simple DB | Redeploy previous version, basic DB backups |
| Growing app, relational DB | Backward-compatible DB migrations, redeploy, manual rollback job |
| Larger system, high uptime requirement | Blue-green or canary, feature flags, automatic rollback |
| Many teams, many features | Feature flags for most new features, canary release for risky ones |
Guidelines:
- Always keep the ability to redeploy an older version.
- Make database migrations safe to roll back or forward.
- For user-facing, critical systems, use canary or blue-green.
- Use feature flags for big or risky changes.
- Automate the rollback action inside your CI/CD platform.
Practicing Rollbacks
Rollback strategies are only useful if they actually work in real life.
Practice them:
- In staging:
- Run a deployment.
- Intentionally introduce a failure.
- Execute your rollback pipeline step.
- Verify:
- The system returns to a good state.
- Data is consistent.
- Logs clearly show what happened.
You can even write automated tests for your deployment and rollback scripts, for example:
- Script that simulates a failed health check and ensures the deployment controller triggers a rollback.
- Check that the environment ends up using the previous version.
A rollback strategy that has never been tested is not a real strategy. Treat rollbacks as a core part of your CI/CD process and test them regularly.
By building and practicing clear rollback strategies, you turn deployments from risky events into routine, reversible operations, which is one of the main goals of CI/CD.
Views: 6
KAHIBARO