Mitigate First, Diagnose Second
Open in the interactive app: practice, quiz, mock interview →In one minute
- During an incident the goal is to end user impact, not to understand it. Understanding can wait for the postmortem; users cannot.
- Most mitigations are generic: roll back, turn the feature off, move traffic away, shed load, add capacity. None needs a root cause.
- Prefer actions that are fast, reversible and well rehearsed, even if they might not be the true fix.
- Keep evidence while you mitigate: snapshot a bad host, save logs, record what you changed and when.
- "We rolled back and it recovered" is a strong clue for diagnosis later, not a substitute for it.
How it works
Why diagnosis is the slow path
Diagnosis is open-ended. You do not know how many hypotheses you will test or how long each takes. Mitigation is a short list of known actions with known costs. If a rollback takes 6 minutes and diagnosis takes somewhere between 10 minutes and 4 hours, the expected impact is far lower if you roll back first and diagnose a healthy system later.
Generic mitigations
A small set of actions fixes most incidents without knowing why they happened:
- Roll back the most recent deploy or config change.
- Disable a feature through its flag or kill switch.
- Drain a bad host, zone or region and send traffic elsewhere.
- Shed load: reject low-priority traffic, turn off expensive features, rate-limit abusive clients.
- Scale out when the cause is capacity.
- Block a specific bad input, client or query pattern.
- Restart as a last resort, because it destroys evidence and often only resets the clock.
Choosing among them
Rank options by three things: how long until it takes effect, how likely it is to help, and what happens if it is wrong. A reversible action that takes 30 seconds and has a 40 percent chance of working is often better than a one-way action that takes 20 minutes and has a 90 percent chance. Try the cheap reversible guess first, check impact, then move on. Correlate with change: if a deploy landed in the 30 minutes before onset, rolling it back is the first candidate even when "it can't be that".
Preserve evidence
Mitigation and evidence can conflict. Before you restart a leaking process, take a heap dump or at least record its memory graph. Before you terminate a misbehaving host, take it out of the load balancer instead and leave it running for later inspection. Save the logs that rotate quickly. Write every action into the incident timeline with a timestamp so the later analysis can tell cause from effect. Azure's guidance makes the same trade: keep failed resources in a quarantined state for forensic analysis rather than discarding them, and build toggles that disable or isolate a faulty component without a redeploy (Azure Well-Architected).
When mitigation is not enough
Some incidents have no generic fix: data corruption that is already written, a dependency that is fully down with no alternative, a security breach. Then the question becomes "how do we limit the damage?": stop writes, put the system into read-only mode, fail closed rather than open, or communicate a workaround. Even here, damage limitation comes before full diagnosis.
Down the stack
Layer 1The contract
The process promises that the incident team will pursue the fastest available action that reduces user impact, that every mitigation is announced before it runs, that each has a stated rollback, and that evidence needed for diagnosis is preserved when doing so costs less than a few minutes. It also promises that the team re-checks impact after each action, rather than assuming success, and keeps going until user-facing indicators are back within SLO.
Layer 2The mechanism
Each generic mitigation has a concrete mechanism. In Kubernetes, kubectl rollout undo deployment/api restores the previous pod template from the Deployment's revision history (old ReplicaSets kept up to revisionHistoryLimit, 10 by default; Kubernetes docs) and performs a rolling update governed by maxSurge and maxUnavailable. A feature-flag kill switch is a value in a flag service; SDKs keep a local cache and receive changes over a streaming connection (server-sent events in several commercial products) or by polling every N seconds. A traffic drain changes load-balancer weights, sets a target to draining so in-flight connections finish within a deregistration delay (300 seconds by default on AWS Application Load Balancer target groups; AWS docs), or removes a DNS record. Load shedding is a check at the front door: if the in-flight request count or queue time exceeds a limit, return 503 with Retry-After immediately, before doing work. The rejection has to be far cheaper than the work, and the aim is to keep latency low for the requests you accept, not to be fair to all of them (AWS Builders' Library).
Layer 3The machine
These actions differ by orders of magnitude in time on real machines. A flag change over a streaming connection reaches SDKs in about a second; a polling SDK at a 30 s interval averages 15 s. A rollback has to schedule pods, pull images (seconds if the old image is still on the node's disk, a minute or more for a large image from a registry), start the process, warm the JIT and caches, and pass readiness probes; for a JVM service with 200 pods and maxSurge: 25% that is often 5 to 15 minutes. A DNS-based drain is bounded by TTL, and some resolvers and client libraries hold records longer than the TTL. Scaling out on fresh VMs takes 1 to 3 minutes to boot plus warmup, and cold caches can push extra load to the database just as you add capacity. Restarting a process discards its heap, open file descriptors and in-memory queues: exactly the state you would want for a memory-leak or deadlock diagnosis, which is why jmap, gcore or a goroutine dump comes first if you can afford a minute.
Why it's built this way
User impact accrues every minute, so time to mitigate dominates incident cost. Root-cause search has unbounded duration, so it should not block the bounded actions. Recent change is the most common trigger of incidents (Google's SRE book estimates roughly 70 percent of outages are due to changes in a live system; Google SRE book), so undoing change is the highest-yield generic fix. Reversible actions let a team try several guesses quickly, so systems are built with flags, rollbacks and drains in advance, before anyone needs them at 3 a.m.
Diagram
flowchart TD
A["Impact confirmed"] --> B{"Change in last 30-60 min?"}
B -->|yes| C["Roll back or disable flag"]
B -->|no| D{"Localised to host, zone or region?"}
D -->|yes| E["Drain it"]
D -->|no| F{"Overload?"}
F -->|yes| G["Shed load or scale out"]
F -->|no| H["Block bad input or degrade feature"]
C --> I{"Impact reduced?"}
E --> I
G --> I
H --> I
I -->|no| B
I -->|yes| J["Stabilise, preserve evidence, diagnose"]Worked example
At 09:12 search latency p99 jumps from 180 ms to 2.4 s and 8 percent of requests time out. The change log shows three entries in the hour before: a search-ranking deploy at 08:51, a config change raising the cache TTL at 09:05, and a new index build that finished at 09:09.
The ops lead lists options:
| Option | Minutes to effect | Chance it helps | Reversible |
|---|---|---|---|
| Revert cache TTL config | 1 | 0.3 | yes |
| Roll back ranking deploy | 9 | 0.3 | yes |
| Switch to previous index | 3 | 0.5 | yes |
| Add 50 percent more search nodes | 12 | 0.2 | yes |
Dividing time by chance of success gives an expected cost per attempt: TTL revert about 3.3, index switch 6, rollback 30, scale-out 60. The IC approves the TTL revert at 09:16; no change by 09:18. The index switch goes at 09:19 and p99 drops to 210 ms by 09:22. Total impact is 10 minutes.
Before switching, the ops lead saved the slow-query log and kept one node on the new index out of rotation. The postmortem later finds the new index had a field mapping that disabled a filter cache, which the preserved node made easy to confirm. Had the team started by profiling queries, the investigation would have taken around 90 minutes of continued timeouts.
In the wild
- Google Cloud, 2025: a kill switch built in advance. A policy change with blank fields crash-looped Service Control in every region on 12 June. The new check had no error handling and no feature flag. SRE had a "red button" for the serving path ready after about 25 minutes and rolled it out within 40. Restarting tasks then overloaded Spanner in us-central1 because Service Control lacked randomized exponential backoff, so that region took up to about 2 hours 40 minutes to recover. Google committed to feature-flagging critical binaries, disabled by default (Google Cloud incident report).
- Cloudflare, 2019: kill the component, fix later. A WAF rule with a regex that backtracked pinned CPUs worldwide. Engineers did not wait to fix the regex: a "global terminate" of the WAF ran at 14:07 UTC and traffic and CPU were normal by 14:09. The rule was rolled back, tested in one city, and re-enabled globally at 14:52 (Cloudflare).
- Facebook, 2021: when the generic mitigations are out of reach. A backbone command took the data centers offline and the DNS servers withdrew their routes. Out-of-band access and internal tools were down, so engineers went to the data centers in person, and hardware and security hardening slowed them. Bringing load back gradually, using drills for major failures, avoided a power surge from restarting everything at once (Engineering at Meta).
Trade-offs
| Option | Strengths | Weaknesses | Choose when |
|---|---|---|---|
| Roll back | Undoes the likeliest cause | Slow for large fleets; not possible after one-way migrations | A deploy preceded onset |
| Feature flag off | Seconds, precise | Only covers flagged code | The new feature is suspected |
| Drain host or zone | Removes a sick part quickly | Remaining capacity must absorb load | Impact is localised |
| Shed load | Protects the core path | Some users get errors on purpose | Overload or a retry storm |
| Restart | Clears bad state | Destroys evidence, often recurs | Nothing else is available |
Pitfalls in production
- Rolling back is impossible because the release included a destructive schema migration. Fix: expand-and-contract migrations so the previous version always works with the current schema. AWS describes the same idea for any format or protocol change: first ship a version that can read the new format but still writes the old one, wait through a bake period, and only then ship the version that writes it (AWS Builders' Library).
- The team debugs a "can't be the deploy" theory for an hour. Fix: if a change landed near onset, undo it first; it is cheap to be wrong.
- Restarts hide a leak that returns every six hours. Fix: capture a heap or goroutine dump before restarting and file the diagnosis as a postmortem action.
- Scale-out makes things worse because new instances stampede a cold cache or the database. Fix: know which dependencies cap your capacity before adding instances.
- Two mitigations run at once, so nobody knows which worked. Fix: one change at a time, announced, with impact checked after each.
- A drain shifts load to a region that then falls over. Fix: check headroom before draining; shed load if headroom is short.
Leadership lens
- In design reviews, ask "how do we turn this off?" for every new feature. No kill switch means no generic mitigation. Google's 2025 Cloud report singles out the crashing code path as not protected by a feature flag (Google Cloud).
- Track time to mitigate separately from time to resolve; reward the first.
- Rehearse rollbacks and drains in game days so they are routine at 3 a.m.
- Make destructive migrations a separate, later release from the code that stops using the old schema.
Check yourself
Why is a reversible 30-second action with a low chance of success often tried before a slow, likely fix?
Show answer
Its expected cost (time divided by chance of success) is small, and if it fails you lose little and still learn something before trying the slower option.
What evidence would you capture before restarting a process suspected of leaking memory?
Show answer
A heap dump or core (
jmap,gcore), memory and file descriptor counts over time, and recent logs; or take the instance out of rotation and leave it running.Why can a rollback fail to mitigate even when the deploy was the cause?
Show answer
The bad version may have written data or run a migration that persists, caches may hold bad entries, or the old version may be incompatible with the new schema.
When is restarting a reasonable mitigation?
Show answer
When state is corrupted or exhausted and no cheaper action exists, ideally after evidence is captured and with the expectation that the problem may return.
Sources and further study
Primary
- Google Cloud incident report, 12 June 2025: triage to red-button in 40 minutes, then the herd effect on recovery.
- Cloudflare: 2 July 2019 outage: the global terminate as the mitigation, and the access problems on the way to it.
- Engineering at Meta: October 2021 outage: why recovery tools must not share fate with what they recover.
Systems docs
- Kubernetes: Deployments:
kubectl rollout undo, revision history and rolling-update limits. - AWS: target group attributes: the 300-second default deregistration delay for draining.
Books
- Site Reliability Engineering (Beyer et al.), chapter 12 "Effective Troubleshooting" and chapter 13 "Emergency Response".
- Site Reliability Engineering, chapter 1 "Introduction", section "Change Management": the figure that roughly 70 percent of outages come from changes.
Other curricula
- AWS Builders' Library: using load shedding to avoid overload: goodput, cheap rejection and testing past the breaking point.
- Azure Well-Architected: incident management process: containment by design, runtime toggles and quarantined evidence.
Watch
- Shrinking Production Incidents - Dan Adams, Google SRE (DevOps Perth): reducing incident duration with mitigation-first habits.
- SREcon17 Americas - Root Cause, You're Probably Doing It Wrong (USENIX): why hunting a single root cause during an outage misleads teams.
Free resources
- Generic Mitigations (O'Reilly): a Google SRE's catalogue of mitigations that work without a diagnosis.
- Effective Troubleshooting (Google SRE book): "make the system work under the circumstances" before finding the cause.
- Emergency Response (Google SRE book): real Google incidents and the role of change in outages.
- Ensuring rollback safety during deployments (AWS Builders' Library): two-phase deployments that keep rollback possible.
- Feature Toggles (Martin Fowler): the kinds of flags, including ops toggles used as kill switches.