Deployment Rollback Strategies
debt(d7/e5/b5/t7)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints.tools list (Capistrano, Deployer, AWS CodeDeploy) are deployment tools, not analyzers that detect missing rollback procedures. The code_pattern notes 'no documented rollback procedure' and 'migrations without down() method' — these require manual review or runtime discovery during an actual failed deployment. No automated tooling catches missing rollback strategies.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix suggests monthly staging testing, but actually fixing missing rollback capability requires: adding down() methods to all migrations, documenting rollback procedures, potentially restructuring database changes to be reversible (add columns before removing old ones per common_mistakes). This spans migration files, deployment scripts, and documentation — multiple files within the devops/deployment component.
Closest to 'persistent productivity tax' (b5). Applies_to shows web and cli contexts from PHP 5.0+, meaning this affects all deployment scenarios. Lack of rollback strategy creates ongoing anxiety and slower deployments (teams deploy less frequently when rollback is risky). However, it doesn't define the system's architecture — it's a process/procedure gap that taxes velocity without fundamentally shaping code structure.
Closest to 'serious trap' (t7). The misconception field explicitly states 'You can always roll back by reverting the git commit' — this contradicts how developers familiar with git expect rollback to work. Git revert feels like a universal undo, but database schema changes persist independently. Common_mistakes reinforces this: 'code reverted, DB schema already migrated — app breaks with old code on new schema.' This trap catches experienced developers who assume version control solves deployment rollback.
Also Known As
TL;DR
Explanation
Rollback options by speed: Feature flags (instant — flip a flag without deploying), Blue-green (instant — switch load balancer to previous environment), Canary (fast — redirect canary traffic to stable), Git revert + redeploy (minutes — depends on CI/CD pipeline speed), Database rollback (slow, risky — migrations may not be reversible). The fastest rollback is the one already in place before the deploy. Database migrations that are not reversible are the most common rollback blocker — always write forward-compatible migrations first.
Diagram
flowchart TD
DEPLOY[New Deploy] --> CHECK{Smoke Tests}
CHECK -->|Pass| LIVE[Live Traffic]
CHECK -->|Fail| RB1[Instant Rollback<br/>Blue-Green switch]
LIVE --> MONITOR{Monitoring}
MONITOR -->|Error spike| RB2[Rollback Options]
RB2 --> FF[Feature Flag off<br/>instant]
RB2 --> BG[Blue-Green switch<br/>seconds]
RB2 --> GR[Git revert + redeploy<br/>minutes]
style LIVE fill:#238636,color:#fff
style FF fill:#238636,color:#fff
style FAIL fill:#f85149,color:#fff
style ALERT fill:#f85149,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Irreversible database migrations — always add columns before removing old ones; never rename in one step.
- No rollback testing — rollback procedures that have never been tested will fail when needed most.
- Assuming git revert is sufficient — code reverted, DB schema already migrated — app breaks with old code on new schema.
- Rolling back without investigating root cause — rollback buys time; the fix still needs to be understood.
Code Examples
# Breaking migration with no rollback path:
ALTER TABLE users RENAME COLUMN email TO email_address;
# Old app code: SELECT email FROM users — now broken
# Rolling back the code: still broken, schema changed
# Only fix: another migration or forward-fix deploy
# Forward-compatible migration — allows rollback:
# Step 1: Add new column (app still uses old column):
ALTER TABLE users ADD COLUMN email_address VARCHAR(254);
UPDATE users SET email_address = email;
# Step 2: Deploy app reading both columns (backwards compatible)
# Step 3: Deploy app using only new column
# Step 4: Drop old column in a later migration
# Rollback possible at any step except after step 4