Debugging in Production
Part IX โ Production Debugging and Prevention
02:14, three responders, zero procedure
Chapter 55 ended with an attributed ledger and joint-verdict optimizations โ peacetime instruments. At 02:14 the refund agent starts authorizing duplicates at volume, the page fires, and three responders improvise three different incidents: one restarts the service (destroying in-flight evidence), one edits the prompt in the dashboard (a multi-variable repair under fire), one announces “we’re investigating” in the status channel and then goes silent for forty minutes. By dawn the bleeding stopped โ nobody knows which act stopped it, the bundle was never frozen, and the postmortem reconstructs courage instead of causation.
OBSERVATION: the incident timeline shows a restart at 02:21 (in-flight requests lost), a dashboard prompt edit at 02:33 (unversioned), and no frozen bundle; three responder narratives disagree on which act restored service. HYPOTHESIS H1 (order failure): the correct acts in the wrong order destroyed evidence and attribution. H2 (blast-radius failure): containment scope was never set, so diagnosis and user harm proceeded in parallel. H3 (evidence failure): no parallel evidence role existed, so every act consumed the responder who should have been freezing. INFERENCE: none yet โ H1/H2/H3 predict different timeline signatures and separate only once live response has a defined order with defined roles.
This chapter’s question: what is the live-incident discipline โ triage order, blast radius control, and evidence capture under pressure โ that keeps a production fire debuggable?
Why “all hands, fix it live” fails first
The obvious move โ everyone debugging at once, fastest fix wins โ fails because speed without order destroys the evidence that prevention requires. Six defects hide behind heroic response:
- Evidence-destroying first acts. Restarts, redeploys, and config flips before the freeze. The system recovers; the defect becomes UNKNOWN forever.
- Unbounded blast radius. Diagnosis proceeds while users keep paying. Nobody decides what to halt, throttle, or fail over โ so the incident bills by the minute while theories form.
- Single-threaded heroics. One responder freezes, diagnoses, communicates, and repairs in sequence. Each role starves the others; the status channel goes dark; leadership pages harder.
- Live prompt surgery. Dashboard edits under pressure โ unversioned, untested, undeployable-as-hash. The Ch30 discipline inverted at the worst moment.
- Narrative communication. “Looks like the retriever” broadcast as fact. Speculation laundered into timeline; the postmortem inherits fiction.
- Fix-forward closure. Service recovers; incident closed without a bundle, repro, or test. Chapter 53’s conveyor never starts because the live phase never fed it.
OPINION: a production incident without a first-fifteen-minutes order is not a response. It is a second incident wearing a pager.
The mental model: two tracks in parallel from minute one โ the containment track (triage order, blast radius, mitigation) and the evidence track (freeze, record, hand off to Chapter 53). One incident commander owns the order and the clock; a separate evidence lead owns the freeze and never diagnoses. Communication runs on a fixed cadence with OBSERVED-vs-INFERRED labeling. Diagnosis begins only after containment and freeze โ a rule, not a suggestion.
The role split is not invented here. Google’s incident-management framework (IMAG) adapts the US Incident Command System โ the same doctrine used for wildfires โ around “three C’s”: coordinate, communicate, control, with distinct Incident Commander, Communications Lead, and Operations Lead roles, and an explicit rule that the commander does not troubleshoot (“Managing Incidents,” in Beyer et al., eds., Site Reliability Engineering, O’Reilly 2016). This chapter’s “evidence lead who never diagnoses” is the same separation-of-concerns pushed one step further for AI systems, where the failing inputs are bit-fragile and a restart is an evidence delete.
The method: the first-fifteen-minutes order with parallel evidence
Execute in this order; the evidence track runs alongside, never after:
- Minute 0โ2: declare and assign. Commander declares SEV by blast radius and reversibility (Chapter 53’s scale), names the evidence lead and the communications role. Everyone else stands by. No act before assignment โ assignment is the first act.
- Minute 2โ5: freeze a slice. Evidence lead snapshots the Chapter 52 bundle for failing requests plus deploy state and index pointer โ a slice, not the ocean. Hash it, timestamp it. If the freeze conflicts with mitigation, freeze the slice first (minutes), then mitigate. A restart without a frozen slice is prohibited by procedure.
- Minute 5โ8: bound the blast radius. Commander picks the reversible containment: throttle the failing path, fail over to a pinned previous deploy, disable the committing edge’s automation (hedge/escalate per Chapter 54) โ one lever, predicted effect stated aloud, logged. Irreversible acts (data deletes, mass refunds) require explicit commander approval with the prediction recorded.
- Minute 8โ15: first divergence, stated carefully. With containment holding and the slice frozen, state the first divergence as OBSERVATION with request hashes โ then H1/H2 with distinct predicted signatures. Broadcast only OBSERVED facts plus labeled hypotheses on the fixed cadence (every 15 minutes for SEV-1, every 30 for SEV-2). INFERENCE is labeled as such in every update.
- Handoff, not heroics. When the clock passes the declared threshold (a setup choice per team โ e.g., 60 minutes without isolated divergence), the commander hands the frozen slice to the Chapter 53 conveyor and the incident moves to mitigation-hold plus queued investigation. Overnight heroics without handoff are how evidence dies tired.
flowchart TD
P["page fires"] --> A["t+0-2: commander declares SEV, names evidence lead + comms; nobody touches the system until assigned"]
A --> F["t+2-5: EVIDENCE TRACK โ freeze a slice (failing requests + deploy state + index pointer), hash + timestamp"]
A --> C["t+5-8: CONTAINMENT TRACK โ one reversible lever (throttle / fail over / disable the committing edge), predicted effect stated + logged"]
F --> D["t+8-15: state the first divergence as OBSERVATION with request hashes; then H1/H2 with distinct predicted signatures"]
C --> D
D --> U["broadcast on a fixed cadence: OBSERVED facts + labeled hypotheses, every cycle"]
U --> HO{"past the declared threshold without an isolated divergence?"}
HO -->|yes| HANDOFF["hand the frozen slice to the Ch53 conveyor; incident -> mitigation-hold + queued investigation"]
HO -->|no| D
LIVE-INCIDENT RECORD (updated on cadence, not from memory):
sev: SEV-___ | commander ___ | evidence ___ | comms ___
t+___: OBSERVED ___ (hashes ___) | INFERRED ___ (labeled H___)
containment: lever ___ (reversible y/n ___) predicted ___ observed ___
frozen slice: b3:___ at t+___ | verdict events: present / UNEVALUATED ___
cadence: updates every ___ min | HANDOFF to Ch53 at ___ with bundle ___
RULE: every broadcast separates what the hashes show from what the room suspects.
OBSERVATION (constructed illustration, not a measured run): the timeline with the order applied shows slice frozen at t+4, throttle lever at t+7 with duplicate rate falling while the slice stays intact, first divergence stated at t+12 with hashes โ versus the actual night where restart preceded any freeze. UPDATED BELIEF: H1 supported for this instance (order, not competence, was the failure); H2 supported as compounding (no containment lever was ever pulled); H3 supported as structural (no evidence role existed). One order addresses all three โ discipline, not heroism.
No restart-before-freeze, no live dashboard surgery, no unlabeled speculation in updates, no single-responder sequencing, and no recovery-without-artifacts closes a live incident. Containment levers with predicted effects and labeled cadence updates close the live phase; the conveyor closes the incident.
Example: the duplicate-rate page, worked in order
The page fires for duplicate authorizations at volume. The commander assigns before anyone touches the system:
# live-fire order: assign, freeze, contain, then diverge (diagnosis last)
declare(sev="SEV-1", commander="___", evidence="___", comms="___") # t+0..2
frozen = freeze_slice(failing_requests(window=10), deploy_state(), index_ptr()) # t+2..5
log(frozen.hash) # MEASUREMENT: b3:___ โ evidence survives whatever follows
lever = contain("throttle auth path to 10%", predicted="duplicate rate falls, queue grows")
log(lever.effect) # OBSERVATION: rate ___ -> ___ ; prediction confirmed / refuted
# Only now: first divergence with hashes, H1/H2 predictions pre-written, cadence updates.
divergence = state_first_divergence(frozen, trials=3) # Ch53 consumes this next
In the constructed case the throttle lever confirms the failing path while the frozen slice preserves bit-exact inputs; the first divergence (scope-less handoff, as in Chapter 53’s case) is stated at t+12 with hashes, and the handoff to the conveyor carries bundle, lever log, and cadence record. The duplicate rate falls under throttle, the queue is worked through the pinned previous deploy, and the postmortem inherits MEASUREMENT instead of recollections. The licensed claim covers this incident under this order โ not incident response in general.
Lab 56: game-day drill with pre-written order predictions (proposed)
PROPOSED, not executed: no author-measured results are reported. The evidence this chapter requires is the reader’s own drill timeline.
Setup. Stage a production-like failure on a non-production endpoint (or tabletop with a frozen historical bundle). Assign commander, evidence, and comms roles in advance. The response order (this chapter’s order vs. the team’s habitual order) is the independent variable; scenario, tooling, and personnel pool are controlled.
Task.
- Before the drill, write H1/H2/H3 with distinct predicted timeline signatures: H1: “habitual order destroys or delays the freeze (restart/edit before slice)”; H2: “habitual response leaves blast radius unbounded past t+8”; H3: “habitual updates merge OBSERVED with INFERRED (unlabeled speculation broadcast).”
- Run the drill twice (habitual order, then this chapter’s order), โฅ2 rounds each; record per-minute timelines verbatim: freeze time, containment time, first labeled divergence, update cadence.
- Hand the frozen slice to a Chapter 53 repro attempt and record whether the repro succeeds from drill artifacts alone.
| Hypothesis | Predicted timeline signature | FORECAST | OBSERVATION (ร2 rounds) | UPDATED BELIEF |
|---|---|---|---|---|
| H1 order | freeze delayed/destroyed | ___ | ___ | live/exonerated |
| H2 radius | unbounded past t+8 | ___ | ___ | live/exonerated |
| H3 labeling | speculation broadcast unlabeled | ___ | ___ | live/exonerated |
Success criterion. Two per-minute timelines, two frozen slices with hashes, a containment lever log with predicted-vs-observed effects, and a repro-attempt verdict from drill artifacts. A confident debrief without timelines is explicitly not completion.
Companion tool: Production Incident Replay Console
What it accepts: the live-incident record with per-minute timeline, the frozen slice with hashes, containment lever logs with predictions, cadence updates with OBSERVED/INFERRED labels, and the Chapter 53 handoff bundle. What it performs: it verifies freeze-before-mitigation ordering from timestamps, checks the containment lever was single, reversible, and prediction-logged, audits that broadcasts separate OBSERVED from INFERRED, replays the slice to confirm the handoff repro succeeds, and refuses incident closure when the conveyor artifacts are missing. What it can establish: whether the live phase preserved debuggability and contained harm โ for the examined incident and timeline only. What it cannot establish: correctness of the eventual diagnosis, optimality of the lever choice, or readiness for novel incident classes. It never treats fast recovery, confident narration, single-responder heroics, agreement in the room, or downstream quiet as response quality. How its output changes your next action: order-verified routes to the conveyor handoff; freeze-violated routes to order retraining with drill evidence; radius-unbounded routes to pre-approved containment levers per path; unlabeled-updates routes to comms-template repair โ each as one intervention with pre-written predictions.
Paper form, sufficient for this chapter:
Incident ___ SEV ___ | freeze at t+___ (hash ___) | lever ___ at t+___ (pred ___ obs ___)
Divergence stated t+___ (hashes y/n) | updates every ___ (labeled y/n ___)
Handoff bundle ___ -> Ch53 repro: succeeds / fails NEXT: conveyor / retrain / levers / templates
Where a software implementation does not yet exist in the reader’s stack, this record is the tool. Order before heroics.
Research lineage: incident command, blameless analysis, and the hindsight trap
Incident Command as doctrine. IMAG (Google) and its ancestor ICS are the reason this chapter opens with assignment as the first act. The recurring failure they were built to prevent โ everyone converging on the problem, nobody coordinating, communication going dark โ is precisely the “three responders, zero procedure” cold open. The “3 C’s” (coordinate, communicate, control) and the fixed-cadence status update are lifted directly; the SRE book’s five-stage loop (prepare, detect, respond, recover, learn) is the frame Part IX as a whole implements, with this chapter owning respond and Chapter 53 owning learn.
Blameless postmortems and Just Culture. Allspaw’s 2012 Etsy essay on blameless postmortems โ built on Dekker’s Just Culture โ established that the postmortem’s job is to surface “the messy details” of how the incident actually unfolded, not to assign fault. This chapter’s insistence on a verbatim per-minute timeline recorded live (not reconstructed from memory afterward) is the operational precondition for a blameless analysis: you cannot analyze what nobody wrote down. Allspaw has since argued blamelessness is “table stakes, nowhere near sufficient” โ the analysis quality depends on the fidelity of the artifacts, which is why the evidence track exists.
The hindsight trap. Cook’s How Complex Systems Fail (1998/2000) names why “reconstructs courage instead of causation” is the default outcome: post-accident attribution of a single “root cause” is a social and psychological artifact, not a technical finding, and hindsight bias makes the responders’ real-time uncertainty invisible after the fact. The OBSERVED-vs-INFERRED labeling on every broadcast is a countermeasure โ it freezes what was actually known at t+12 before hindsight rewrites it as obvious.
Evidence-first response. The “freeze a slice before you restart” rule is the incident-response analogue of digital-forensics order-of-volatility: capture the most volatile evidence (in-flight requests, process state) before actions that destroy it. In AI systems the volatile evidence is the exact failing input plus the resolved prompt and retrieval set โ none of it reconstructable after a redeploy.
Recovery time is not a quality signal. The VOID (Verica Open Incident Database), the largest published corpus of incident analyses โ roughly 10,000 incidents from about 600 organizations โ reports two findings that bear directly on this chapter’s anti-claims (Verica, VOID Reports, 2021โ). First, MTTR is not a viable reliability metric: incident durations are heavily right-skewed, so an average is dominated by a handful of long tails and predicts almost nothing about the next incident. Second, incident duration and severity are essentially uncorrelated โ long incidents are often trivial, short ones sometimes critical. Both results are why the companion tool refuses to read fast recovery as response quality, and why this chapter treats SEV as a declared setup choice rather than something the clock later reveals.
Bounds: IMAG is Google’s adaptation and one of several (PagerDuty, incident.io, FEMA ICS differ in detail); blameless-postmortem practice is well-adopted but its effectiveness is argued, not measured; Cook’s essay is a synthesis of safety-science observation, not a controlled study; the VOID findings are observational over a large but self-selected set of public incident reports. The transferable core is the structure โ assign before acting, separate the evidence role, record the timeline live, label observation vs. inference, and do not mistake a short outage for a good response โ not any specific org chart.
Reusable procedure: run every live incident in order
- Assign first โ commander, evidence, comms before any technical act.
- Freeze a slice โ hashed bundle within five minutes; no restart before it.
- Bound the radius โ one reversible lever, predicted effect, logged outcome.
- State divergence carefully โ hashes cited, hypotheses labeled, cadence fixed.
- Hand off, don’t hero โ slice to the conveyor past the declared threshold.
Failure modes
- Restart-first reflex. Evidence destroyed in the opening act. Recovery purchased with unknowability.
- Unbounded billing. Diagnosis while users pay. Containment is a decision; delay is also a decision.
- Hero sequencing. One responder, all roles, in series. Everything starves; the channel goes dark.
- Live dashboard surgery. Unversioned edits under fire. The discipline inverted when it costs most.
- Speculation broadcasts. Hypotheses announced as findings. Fiction enters the timeline permanently.
- Recovery-without-artifacts. Service up, incident “closed,” conveyor starved. The same fire, scheduled.
- Lever stacking. Three containment acts at once. Attribution of the recovery destroyed mid-save.
- Cadence collapse. No updates or a flood of them. Trust and coordination both require rhythm.
Limits, per contract: one console review covers one incident under one timeline; it does not certify diagnoses, does not bless lever choices across incident classes, and stays UNKNOWN where timestamps or slices are missing.
References
- Betsy Beyer, Chris Jones, Jennifer Petoff, and Niall Richard Murphy (eds.). Site Reliability Engineering: How Google Runs Production Systems โ chapters “Managing Incidents” and “Postmortem Culture.” O’Reilly, 2016. https://sre.google/sre-book/managing-incidents/
- Google. Incident Management Guide (IMAG). https://sre.google/resources/practices-and-processes/incident-management-guide/
- John Allspaw. Blameless PostMortems and a Just Culture. Etsy Code as Craft, 2012. https://www.etsy.com/codeascraft/blameless-postmortems/
- Sidney Dekker. Just Culture: Balancing Safety and Accountability (2nd ed.). Ashgate, 2012.
- Richard Cook. How Complex Systems Fail. Cognitive Technologies Laboratory, University of Chicago, 2000. https://how.complexsystems.fail/
- Verica. The VOID (Verica Open Incident Database) Reports. Verica, 2021โ. https://www.thevoid.community/ (~10,000 incidents / ~600 organizations; MTTR is not a viable metric; incident duration and severity are uncorrelated.)
- PagerDuty. Incident Response Documentation and Postmortem Documentation. https://response.pagerduty.com/ (cross-ref Ch 53 conveyor).
Debugging Checklist
- Roles assigned (commander, evidence, comms) before any technical act?
- Frozen slice hashed within five minutes (no restart before it)?
- Single reversible containment lever with predicted effect logged?
- First divergence stated with request hashes (not narratives)?
- H1/H2 predictions pre-written with distinct signatures?
- Cadence updates separate OBSERVED from INFERRED every cycle?
- Handoff to the Chapter 53 conveyor with bundle + lever log?
- No live dashboard edits, stacked levers, or speculation broadcasts?
- No fast-recovery, heroics, agreement, or quiet cited as response quality?
What This Chapter Established
- Live-incident discipline: the first-fifteen-minutes order with a parallel evidence track, reversible containment, labeled cadence, and conveyor handoff โ demonstrated on the constructed 02:14 duplicate-rate page, no measured runs claimed.
- The order/radius/evidence separation (H1/H2/H3) via per-minute timelines, plus the freeze-before-mitigation rule.
- Lab 56 as a proposed game-day drill the reader executes; the Production Incident Replay Console contract (accepts/performs/can-establish/cannot-establish/next-action).
- What was NOT proved: any diagnosis-correctness claim, any lever optimality across classes, or any readiness certification. Debuggability preserved under fire; nothing universal.
- Position in the arc and Part IX’s close: Chapter 52 emits the evidence, 53 conveys it to durable tests, 54 enforces known checks at runtime, 55 books the economy, this chapter keeps the live fire debuggable. Production debugging and prevention, end to end.
- Research grounding: incident command (IMAG/ICS “three C’s,” commander-does-not-troubleshoot), blameless postmortems and Just Culture (Allspaw, Dekker) requiring a live verbatim timeline, the hindsight/root-cause trap (Cook), order-of-volatility evidence capture, and the VOID’s large-corpus finding that recovery time is heavy-tailed and severity-uncorrelated โ so fast recovery is not a response-quality metric.
Next
Part IX closes with the method proven under load โ but proven at full depth, with hours and roles and frozen slices. Real practitioners rarely get full depth: sometimes they get ten minutes between meetings, sometimes an hour before the review, sometimes the full incident with every role staffed. The question Part X answers is how the same method compresses without corrupting: what survives at each budget, and what is honestly skipped. Chapter 57, “The Ten-Minute Debug,” states the minimal procedure; what ten minutes can and cannot establish is its chapter’s to establish, not this one’s.