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.
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.
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.
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 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.
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.
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.
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 latest tutorials, guides, and insights on AI, DevOps, Cloud, and Infrastructure delivered directly to your inbox.
Explore more articles in this category
We used to ship code and turn it on in the same breath, so every deploy was a bet. Feature flags split those two events apart and made rollbacks a config toggle.
Our best engineer quit citing on-call. We rebuilt the whole thing: saner rotations, runbooks that actually help at 3am, and escalation that doesn't punish asking for help.
Most SLI dashboards track things nobody notices. Here's how we picked the handful of signals that map to real user pain, and dropped the vanity metrics.
Evergreen posts worth revisiting.