Blameless Postmortems: The Template and Facilitation That Works
Our early postmortems quietly assigned blame and taught people to hide mistakes. Here's the template and the facilitation rules that finally made them honest and useful.
Key takeaways
- Our early postmortems quietly assigned blame and taught people to hide mistakes.
- Here's the template and the facilitation rules that finally made them honest and useful.
On this page
Blameless Postmortems: The Template and Facilitation That Works#
Our first year of postmortems were blameless in name only. The doc said "no blame," but everyone in the room knew the meeting was really about which engineer pushed the bad config. People got defensive, timelines got vague, and the real lesson, that our deploy tool let a single typo take down production, never made it into an action item. Worse, the on-call engineer who found the problem learned to keep their head down next time.
A postmortem that assigns blame teaches people to hide incidents. That's the exact opposite of what you want. It took us a rewrite of both the template and how we ran the meeting to fix it.
The template we settled on#
Keep it short enough that people actually fill it out. Ours is one page with these sections, in this order:
# Incident: <short name> Date: <yyyy-mm-dd> Severity: SEV2
## Impact
- Who/what was affected, for how long, measured. ("Checkout failed
for ~12% of EU users for 34 minutes; ~$18k in delayed orders.")
## Timeline (UTC, from monitoring/logs, not memory)
- 14:02 Deploy of order-service 1.9.0 begins
- 14:06 5xx rate on /checkout climbs to 40%
- 14:09 First alert fires (SLO burn rate)
- 14:11 On-call acknowledges
- 14:23 Rollback initiated
- 14:36 Error rate back to baseline
## What happened (contributing factors, plural)
## What went well
## Where we got lucky
## Action items (owner + due date + tracking link)
Two sections earn their place that beginners skip. "Where we got lucky" surfaces the near-misses, the thing that saved you this time and won't next time. And "contributing factors" is deliberately plural, because real incidents never have one cause.
Timeline from logs, not memory#
The single biggest quality jump came from banning "I think it was around 2ish." Every timeline entry cites a source, a monitoring graph, a deploy log, a Slack timestamp. Memory reorders events and inflates how fast people responded. Logs don't.
filter @message like /deploy|rollback|alert/
| sort @timestamp asc
| fields @timestamp, @message
We paste the raw log query results into the doc first, then narrate around them. It also depersonalizes things, "the deploy started at 14:02" reads very differently from "Priya deployed at around 2."
The facilitation rules that make it blameless#
The template is maybe a third of it. The meeting is where blame either gets designed out or sneaks back in. Our facilitator follows a few hard rules:
Replace names with roles in discussion. "The on-call engineer restarted the pod," not "Dave restarted the pod." It sounds pedantic. It changes the whole temperature of the room.
Ban the word "should have." "The engineer should have caught it in review" is blame wearing a lab coat. Reframe to system: "our review process didn't flag config changes, so a reviewer had no easy way to catch it." Now you have an action item instead of a scapegoat.
Ask "what made this the reasonable thing to do at the time?" People act rationally given what they knew. If someone ran a risky command, the question isn't why were they careless, it's why did the system make that command look safe. That reframe found us a CLI with no confirmation prompt on destructive actions.
The five-whys trap#
Five-whys is popular and it's a trap when run naively, because it funnels a messy incident into a single linear chain and stops at "human error." We hit "why did the engineer make a typo, because they were rushing" and almost wrote "be more careful" as the fix. Useless.
We switched to asking for contributing factors in parallel, then testing each: "if this one factor had been absent, would the incident still have happened?" For our config outage the answer was no for three separate factors: no schema validation on the config, no canary stage, no confirmation on the deploy. Three real action items instead of one blame sentence.
Action items that don't rot#
Most postmortem actions die in a doc nobody reopens. Our rule: every action item has a named owner, a due date, and a ticket link, or it doesn't count. Vague ones ("improve monitoring") get rejected in the meeting. And we track completion, the number that matters is the percentage of postmortem actions actually done within their due date.
Action item: Add JSON-schema validation to config deploy pipeline
Owner: @maria Due: 2026-07-18 Ticket: INFRA-2231
We review open postmortem actions in the weekly ops sync. When completion rate dropped below 60% one quarter, that itself became a discussion, and it correlated neatly with a repeat incident from an action we'd written and never done.
The call we'd make#
Fix the facilitation before you polish the template. A perfect template run by someone who lets "should have" and first names into the room will still produce blame and still teach people to hide. Train one good facilitator, give them the authority to reframe language live, and measure action-item completion, not how many postmortems you wrote. A postmortem nobody acts on is just a nicely formatted apology.
Get the DevOps Troubleshooting Cheat Sheet
Subscribe and get our free one-page reference for the errors that eat an afternoon — CrashLoopBackOff, OOMKilled, Terraform state locks, and more — plus new guides as we publish them.
Token Budgeting for Long-Context Prompts: What to Cut First
A 180k-token context window is not a license to stuff everything in. Here's how we cut prompt size 60% without hurting answer quality, and what to trim first.
AWS vs Azure vs GCP Pricing in 2026 — Real Cost Comparison
The three big clouds are closer on list price than the sales decks suggest. Where they actually diverge is discounts, egress, and Windows licensing.
More from DevOps
Explore more articles in this category
GitLab's New Rate Limits: What to Fix Before Oct 19
GitLab is capping unauthenticated API calls at 60 an hour starting October 19, and the preview windows land before most teams will have noticed.
Storm-3068: A CI/CD Pipeline Is a Kubeconfig Exfiltration Machine
Microsoft's Storm-3068 report used zero malware to steal Kubernetes credentials, just a password reset, a pipeline edit, and permissions nobody had scoped down.
Docker Cloud Sandboxes: Why Agents Need MicroVMs, Not Containers
Docker put AI coding agents in hosted microVMs instead of containers, because a container was never the isolation boundary this job needed.
You might have missed
Evergreen posts worth revisiting.