Overview
Per google-sre-postmortem (opens in new window):
"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 (opens in new window))
"Writing a postmortem is not punishment - it is a learning opportunity for the entire company." (google-sre-postmortem (opens in new window))
The blameless framing is load-bearing. Per google-sre-postmortem (opens in new window), 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."
When to use
Per google-sre-postmortem (opens in new window), 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.
Step 1 - Author the document
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.
Step 2 - Blameless review
Per google-sre-postmortem (opens in new window): "Postmortems are not punishment."
Reviewers should:
Step 3 - Action item discipline
Action items must have:
The action items are the post-mortem's value. Without them, the document is paperwork.
Step 4 - Approval + closure
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.
Step 5 - Storage
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).
- ...Worked example - INC-1234 Stripe webhook failure (SEV-2)
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-patterns
| 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 (opens in new window) 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. |
Limitations
References
Deep reference for the post-mortem-author SKILL.md. The full per-incident section skeleton to copy when authoring a blameless post-mortem. Fill every section; the Action items table is load-bearing - a post-mortem without owned, dated, measurable action items is paperwork.
Store one markdown file per incident under a stable directory (for example docs/postmortems/) with an incident-ID-and-date filename.
# Post-mortem - `INC-XXXX` - <one-line title>
**Status:** Draft | Review | Approved | Action items closed
**Severity:** SEV-n
**Authors:** <incident commander>, <lead investigator>
**Date authored:** YYYY-MM-DD **Incident date:** YYYY-MM-DD
**Reviewers:** <eng manager>, <SRE lead>, <product>
## Summary
2-3 sentences: what happened, who was affected, how long, what was done.
## Impact
- **Users affected:** count and % of MAU.
- **Revenue impact:** amount (state deferred vs lost).
- **SLO debt:** % of the monthly availability budget burned.
- **Reputational:** support tickets, social reach.
## Timeline
Chronological events, one row each, with a UTC timestamp and a source link.
| Time (UTC) | Event | Source |
|------------|-------|--------|
| ... | ... | ... |
## Root cause
What happened, in detail. Not who. The system is the grammatical subject.
## Contributing factors
Every condition that allowed the incident (test gap, threshold too lenient,
missing staging traffic, ...). List all; incidents rarely have a single cause.
## What went well
The positives - what mitigated faster than expected. Per
[Google SRE, Postmortem Culture](https://sre.google/sre-book/postmortem-culture/),
post-mortems should call these out too.
## Action items
| ID | Action | Owner | Priority | Due | Success criterion |
|----|--------|-------|----------|-----|-------------------|
| AI-1 | ... | one named person | P0-P3 | concrete date | measurable "done" condition |
## Lessons learned
What the team knows now that it did not before.
## Postmortem trigger
Which trigger criteria this incident met (user-visible, duration, revenue, SLO).Two fields carry the most weight. Root cause must read as a property of the system, never of a person. Action items must each have one named owner, a concrete due date, a priority, and a measurable success criterion; without all four the item does not get acted on and the same incident recurs.
- Card payments failed for 38 minutes on Friday - write-up due Monday
- Seven weeks on, the auditor wants a record of the July 23 edge outage
- We dropped 4,900 settlement events overnight - write-up goes to our partner today
- Two things off last week's ops log, both need closing out
- Q3 incident summary for the compliance pack - due Friday