Build-an-X workflow that produces a blameless post-mortem from an incident - captures the timeline (chronological event sequence with sources), root cause analysis (what + why, not who), impact (users / revenue / SLO debt), action items (with owners + due dates + measurable success criteria), and "what went well" (intentional). Per Google SRE: "Blameless postmortems are a tenet of SRE culture." Use after every user-visible incident, not just severe ones.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
"A postmortem is 'a written record of an incident, its impact, the actions taken to mitigate or resolve it, the root cause(s), and the follow-up actions to prevent the incident from recurring.'"
"Blameless postmortems are a tenet of SRE culture." (google-sre-postmortem)
"Writing a postmortem is not punishment - it is a learning opportunity for the entire company." (google-sre-postmortem)
The blameless framing is load-bearing. Per google-sre-postmortem, the document must "focus on identifying the contributing causes of the incident without indicting any individual or team for bad or inappropriate behavior" - assuming "everyone involved in an incident had good intentions and did the right thing with the information they had."
Per google-sre-postmortem, common triggers include:
"user-visible downtime, data loss, on-call interventions, extended resolution times, and monitoring failures."
Author a post-mortem after every such incident - not just sev-1. Lower-severity incidents accumulate context that prevents the sev-1.
Copy the full section skeleton from references/post-mortem-document-template.md and fill every section. The required sections, in order:
The worked example below fills this skeleton for a real SEV-2.
Per google-sre-postmortem: "Postmortems are not punishment."
Reviewers should:
Action items must have:
The action items are the post-mortem's value. Without them, the document is paperwork.
The post-mortem isn't "done" until:
The post-mortem is "closed" when all action items ship - typically 2-4 weeks. A 6-month-old open post-mortem is a process failure.
docs/postmortems/
├── INC-1234-stripe-webhook-2026-05-04.md
├── INC-1235-cache-invalidation-2026-05-12.md
├── INC-summary-2026-Q2.md ← rollup
└── README.mdMarkdown + git. Quarterly rollup identifies patterns:
## Q2 2026 incident summary
**Total incidents:** 12
**SEV-1:** 1
**SEV-2:** 6
**SEV-3:** 5
**Patterns:**
- 4 of 12 (33%) were "test gap" - the failing condition wasn't
in the test suite. Action: invest in
test-coverage-targeter
+ property-based testing.
- 3 of 12 (25%) involved canary metrics; 2 of those proceeded
through canary gate. Action: review thresholds (per AI-2 from
INC-1234).
- ...The skeleton from Step 1, filled for a real incident.
Summary. A v1.4.5 deploy introduced a null-metadata crash in the Stripe webhook handler; ~12,400 customers (4.3% of MAU) hit failed checkout completions for 23 minutes until rollback.
Impact. ~$140,000 in delayed (not lost) orders; 32% of the monthly availability budget burned; 47 support tickets.
Timeline (excerpt).
| Time (UTC) | Event | Source |
|---|---|---|
| 14:00 | Deploy of v1.4.5 to canary (5% traffic) | CD pipeline log |
| 14:23 | First Sentry alert: NullPointerException at WebhookHandler:42 | Sentry |
| 14:30 | Canary window ends within thresholds; promoted to 100% | CD pipeline |
| 14:42 | PagerDuty SLO burn-rate alert; incident declared SEV-2 | PagerDuty |
| 14:58 | Rollback complete; error rate returning to baseline | Datadog |
Root cause (what, not who). The v1.4.5 handler added a path for Stripe's
payment_intent.partially_funded event that called
payment.metadata.get("internal_id"); for ~3% of events metadata was null,
the exception was uncaught, the handler returned 500, and Stripe stopped
retrying, so fulfillment never triggered. The canary stage saw the error rate
rise (0.4% vs 0.3% baseline) but stayed under the 1.5x rollback threshold, so
prod-canary-validator returned PROCEED with WARNING and the gate was acked.
Contributing factors. (1) test gap - no unit test for the null-metadata case; (2) canary threshold too lenient for a low baseline; (3) staging carries almost no Stripe webhook traffic, so the new event type was never exercised pre-deploy.
Action items.
| ID | Action | Owner | Priority | Due | Success criterion |
|---|---|---|---|---|---|
| AI-1 | Unit test for partially_funded with null metadata | Bob | P1 | 2 days | Test in WebhookHandlerTest.kt fails against the bug, passes after |
| AI-2 | Tighten canary error-rate threshold 1.5x -> 1.3x | SRE | P2 | 1 sprint | canary-thresholds.yml updated; one normal canary passes |
| AI-3 | Staging fixture covering all Stripe event types | Bob | P2 | 1 sprint | Staging "events by type" metric shows all types > 0 |
What went well. Sentry caught the regression at 14:23, well before the PagerDuty page; rollback finished in 7 minutes, inside RTO. Diagnosis came from the Sentry stack trace alone, with no production debugging.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Blame language | Defeats the blameless principle; team stops authoring post-mortems honestly. | Per Google SRE: focus on contributing causes, not individuals (Step 2). |
| Action items without owner / due date | Nobody acts; same incident recurs. | All four fields required (Step 3). |
| Skipping post-mortems for "small" incidents | Lower-severity context that prevents big incidents is missed. | Author per google-sre-postmortem trigger criteria (Step 1). |
| Post-mortem stored in private docs | Org learning capped at the team. | Public to org (per Google SRE pattern). |
| One-shot post-mortem with no follow-up | "Closed" but action items stale; recurrence likely. | Track action items in tracker (Step 4); post-mortem closed only when all done. |
| Post-mortem authored 2+ weeks after incident | Memory faded; details lost. | Author within 5 business days. |
prod-canary-validator - sibling: canary verdict; post-mortems often surface threshold
tuning needs.