Drill — Write the Postmortem
The incident is over. identity-api recovered at 14:33 UTC, everyone's gone back to what they were doing before their phone buzzed, and now someone has to write it up. That someone is you — primary on-call for the incident this drill hands you. What you get is not a tidy timeline; it's exactly what a real postmortem author gets: a PagerDuty export, three Slack channels pasted together out of order, and a page of your own scratch notes typed one-handed while you were also trying to fix the thing. Your job is to turn that pile into a real document — a factual timeline with the opinions and the noise stripped out, a five-whys root cause that survives being pushed past the first answer that sounds plausible, and action items specific enough that someone could actually be held to them. Write your own draft before you open any answer key below; the point of this drill is the writing, not the reveal.
Imagine you're writing up what happened after a big class science-fair mess — glue everywhere, someone's volcano didn't work, a teacher had to step in. You've got a stack of raw material: a couple of kids' messy accounts of what they remember, a text from your mom about what time she picked you up, and your own foggy memory of the afternoon. A good write-up doesn't just staple all of that together. It sorts out what actually happened and in what order, throws out anyone saying "well obviously Jamie wasn't paying attention" because that's not a fact, and it doesn't stop at "the volcano didn't work" — it keeps asking why until it lands on "nobody tested the baking-soda ratio before the actual fair," which is something you can actually fix next time. That's this whole drill: turn a messy pile of raw memory into a clean, useful, blame-free account.
How this drill works
☺ Like you're 10: You get the same messy pile a real postmortem author gets — write your own version first, then check it against the answer key underneath each step.
This drill picks up exactly where the incident-response tabletop drill left off: the identity-api login outage, resolved at 14:33 UTC after 31 minutes. If you haven't run that drill, you don't need to — everything you need is below. What you don't get below is a clean account. You get the same raw, contradictory, occasionally opinionated material a real incident leaves behind, and three jobs to do with it, in order: build a factual timeline, run the five whys to an actual systemic cause instead of the first thing that sounds like one, and write action items specific enough to survive contact with next quarter's sprint planning. Each step below is a "lab" box with something concrete to produce, followed by a Try it prompt and an answer key you should only open after you've actually written something. At the end, a scoring checklist grades your draft against the mistakes real postmortems make most often — not against a vibe.
Write your own timeline, your own five-whys chain, and your own action items before opening a single <details> box. This drill is graded on the gap between what you produced and what the raw material actually supports — you can't see that gap if you read the answer first. The full template this drill is drilling — Summary, Timeline, Root cause(s), Impact, What went well, What went poorly, Action items — comes straight from postmortems & blameless culture; read that page first if any section name below is unfamiliar.
The scenario: identity-api's postmortem is due
☺ Like you're 10: The fire's out, three teams noticed it happen, and the rule says a real write-up is mandatory — not optional because it "only" lasted half an hour.
identity-api is core-platform's login and token-issuance service — the one every other surface calls before it lets a user do anything. At 14:02 UTC on Tuesday, 2026-08-11, its fast-burn alert paged you, its primary on-call. By 14:08 it was a confirmed SEV1 with three downstream teams independently reporting impact. By 14:33 it was fully resolved. Under this course's own postmortem-trigger rule — any incident that breached an SLO, burned a meaningful slice of the error budget, or involved a formal SEV1 declaration gets a mandatory full postmortem, no matter how short — this one clears the bar on all three counts, and you're drafting it, due for review at Thursday's incident-review meeting, 2026-08-13.
| Thing | Value |
|---|---|
| Service | identity-api — login & token issuance, owned by core-platform |
| Availability SLO | 99.95% non-5xx, rolling 30 days — budget: 21.6 min / 30 days |
| Dependency at fault | Shared Redis session cache, owned and operated by cache-infra (a separate team) |
| Incident window | 14:02–14:33 UTC, Tuesday 2026-08-11 (31 minutes, first page to formal resolution) |
| You are | Primary on-call, core-platform-oncall — and the postmortem's author |
The raw material — notes, exactly as they were left
☺ Like you're 10: Nobody handed you a clean story — you got a phone export, three chat windows, and your own scratchy notes, all jumbled and in three different time zones.
This is everything that exists about the incident right now, pasted in roughly the order it was collected, not the order things happened. Read all of it before you write a single line of your own timeline — and notice, before you even start sorting it, that it's already carrying opinions, guesses, and at least one flat-out irrelevant message mixed in with the facts.
── RAW 1: PagerDuty incident export (all times UTC, PagerDuty account default) ──
Incident #48213 — identity-api fast-burn (page-fast tier)
14:02:11 TRIGGERED service: identity-api urgency: high
14:02:44 ACKNOWLEDGED by dana.reyes
14:07:58 NOTE (dana.reyes): escalating to SEV1, paging Ops Lead + Comms Lead per matrix
14:11:20 NOTE (system): related change detected — redis-fleet-patch-2026-08-11
(scheduled maintenance window, auto-triggered rollout)
window started: 14:01:02 UTC
14:11:35 NOTE (dana.reyes): paging cache-infra-oncall, cache hit ratio collapsed
14:23:41 NOTE (priya.kapoor, cache-infra): repointed clients to healthy primary
14:33:07 RESOLVED by dana.reyes── RAW 2: Dana's scratch notes (typed during the incident, US Eastern / EDT, UTC-4) ──
10:02am - phone screaming again. ident-api fast-burn, both windows lit.
2.8% err. holding at sev2 for now, setting a 5 min recheck timer
10:08am - recheck. NOT better, 34% failing now?? web-frontend AND mobile
AND payments all yelling in #on-call-general at once. ok this is sev1.
paging full IC structure, I'm IC, pulling in an ops lead + comms lead
10:11am - cache hit ratio graph is a cliff. 97% -> 4%. something's wrong
with redis and it is NOT on our side of the fence. paging cache-infra.
honestly feels like every time cache-infra touches redis something
breaks downstream, this keeps happening
10:16am - support queue climbing fast, comms posted a status page update.
good, don't want to wait around for a root cause before saying SOMETHING
10:23am - priya says she found it — a redis patch caused a failover
storm, she's repointing our client connections now. error rate
actually dropping, 51 -> 22 -> 9 in real time, nice
(not sure exactly when that patch went out, maybe around 2:15pm? need
to check the change log properly before this goes in the writeup)
10:26am - !!! error rate jumped back up, 4% -> 13%. priya's fix only
lasted like ninety seconds, kind of wish that had been tested a
little more before she rolled it out honestly
10:29am - ok it's actually recovering now, 13 -> 2 -> 0.06
10:33am - 5 straight minutes under baseline. calling it resolved.
writing this up properly tonight, need coffee first── RAW 3: #core-platform-oncall — Slack, pasted unordered, browser-local times ──
[10:06 AM] web-frontend-oncall: login button just spinning forever for a
chunk of our users, anyone else seeing this
[10:07 AM] mobile-oncall: token refresh failing app-wide on iOS + Android,
users getting logged out mid-session
[10:07 AM] payments-oncall: can't verify buyer sessions, checkout is
effectively blocked for anyone who isn't already mid-flow
[10:14 AM] dana.reyes: support queue up to 43 tickets tagged "can't log
in" (baseline ~3), climbing about 6/min over the last 8 min
[10:14 AM] dana.reyes: 11 new 1-star app store reviews in the last hour
mentioning login, posting a status page update now
[9:41 AM] marcus.chen: anyone still going to the release retro Thursday
3pm? trying to figure out the room booking
[10:31 AM] dana.reyes: lol my dog just walked across my keyboard mid
incident, sorry for any typos above
[10:34 AM] dana.reyes: resolved. 31 min start to finish. postmortem
incoming, full 5-whys, this is going to the review meeting Thursday── RAW 4: #cache-infra-oncall — Slack, pasted unordered, Slack default display (no date/tz shown) ──
[4:11 PM] priya.kapoor: got pinged by core-platform, checking our fleet now
[4:16 PM] priya.kapoor: ok found it — 4 failovers back to back on the
fleet in about 90 seconds during the scheduled patch window. some kind
of split during rollout. identity-api's client is still holding
sockets to the old primary
[4:23 PM] priya.kapoor: repointing their client config at the confirmed
stable node, forcing a reconnect now
[4:26 PM] priya.kapoor: spoke too soon — their error rate jumped back up
2 min later. pretty sure that's a bunch of zombie connections on
identity's side finally timing out and reconnecting badly all at once.
not really on us, that's a client-side pool config thing
[4:35 PM] priya.kapoor: retro note for us separately — we don't actually
alert on failover *frequency* on this fleet, individual failovers are
totally normal and expected. we only found out about the 4-in-90s
burst because core-platform was already paging us about it. worth
fixing on our end regardless of what identity-api doesOne more thing exists: Ellie already pulled the traffic numbers so you don't have to re-derive them — this drill is about writing the postmortem, not re-running the SLI arithmetic that the SLO drill already covers.
| Metric, 14:02–14:33 UTC window | Value |
|---|---|
| Total identity-api requests | 1,922,000 |
| Requests returning 5xx | 173,000 (9.0% volume-weighted average; peaked at 34% at 14:08, relapsed to 13% at 14:26:30) |
| Error budget consumed | ≈2.8 of the 21.6 minutes in identity-api's 30-day budget — about 13% of a full month's budget, in one incident |
| Support tickets tagged "can't log in" | 43 (baseline ~3), climbing ~6/min at peak |
| App-store reviews | 11 new 1-star reviews within the hour |
| Teams affected | web-frontend, mobile-clients, payments (all downstream of identity-api, none of them own the fault) |
The single most common mistake with raw material like this is to lightly reformat it and call it a timeline — turn Dana's scratch notes into bullet points, keep the commentary, ship it. Everything above is source material, not draft copy. Some of it is fact (PagerDuty's timestamps, Ellie's tallied numbers). Some of it is a guess that needs checking (Dana's "maybe around 2:15pm?" against the changelog's actual 14:01:02 UTC). Some of it is opinion dressed as observation ("every time cache-infra touches redis something breaks," "wish that had been tested a little more"). And at least one line is pure noise that doesn't belong in the document at all. Sorting those four categories apart is the actual skill this drill is testing.
Step 1 — build the factual timeline
☺ Like you're 10: One list, one time zone, only things that actually happened — no opinions, no guesses you haven't checked, no jokes about the dog.
- Pull every timestamped fact out of all four raw sources and convert everything to UTC — Dana's notes are EDT (UTC-4), Priya's Slack messages show Slack's local display with no date or offset attached (work out from context that cache-infra is on CEST, UTC+2, and convert).
- Reconcile the one direct conflict: Dana's scratch note guesses the Redis patch "maybe around 2:15pm," unverified. PagerDuty's own change-detection note gives an authoritative timestamp. Use the authoritative one, not the guess — and don't silently drop the fact that a guess existed if it shaped anyone's early understanding.
- Strip every line that's commentary, blame, or irrelevant chatter rather than a fact — Dana's "every time cache-infra touches redis" and "wish that had been tested a little more," Priya's "not really on us," and Marcus's retro-scheduling message all have to go. None of them are events that happened in the incident.
- Keep human actions in the timeline in the same neutral tense as system events — "Priya Kapoor repointed identity-api's client connections to the healthy primary at 14:23 UTC" is a fact, written the same way "error ratio crossed 1.44% at 14:02 UTC" is a fact.
Write your own Timeline section now — timestamps in UTC, one line per event, from 14:01 through 14:33. Then open the answer key below and compare line by line, not just the general shape.
See the model Timeline section
| Time (UTC) | Event |
|---|---|
| 14:01:02 | cache-infra's scheduled Redis maintenance window begins (change redis-fleet-patch-2026-08-11, auto-triggered rollout) |
| 14:01:15–14:02:35 | Four failovers occur on the Redis fleet within approximately 90 seconds during the rollout |
| 14:02:11 | identity-api fast-burn alert triggers (1h/5m burn-rate windows, page tier); error ratio 2.8% |
| 14:02:44 | Primary on-call (Dana Reyes) acknowledges the page; incident held at SEV2 pending a recheck |
| 14:08 | Recheck: error ratio 34%. web-frontend, mobile-clients, and payments independently report impact. Incident escalated to SEV1; full Incident Command structure invoked |
| 14:11 | identity-api's Redis cache-hit ratio found collapsed from 97% to 4%. cache-infra-oncall (Priya Kapoor) paged |
| 14:14–14:16 | Support tickets tagged "can't log in" climb from a baseline of ~3 to 43; 11 new 1-star app-store reviews recorded within the hour |
| 14:16 | Comms Lead posts an external status-page update acknowledging impact, before root cause is confirmed |
| 14:16 (cache-infra) | Priya Kapoor identifies four failovers within ~90 seconds on the Redis fleet during the patch rollout; identity-api's client is still holding connections to the old primary |
| 14:23 | Priya Kapoor repoints identity-api's client connections to the confirmed-healthy Redis primary. Error ratio falls: 51% → 22% → 9% |
| 14:25 | Error ratio at 4%, holding for ~90 seconds |
| 14:26:30 | Error ratio relapses: 4% → 13%. Cause: a batch of identity-api's own pooled connections, left stale by the earlier failover, time out and reconnect simultaneously |
| 14:29 | Connection pool fully cycled onto healthy connections; error ratio falling — 13% → 2% → 0.06% |
| 14:33:07 | Error ratio at 0.04%, sustained for 5+ minutes. Incident formally declared resolved |
Notice what's absent: no line says a team "should have known better," no line editorializes about whether Priya's fix was tested enough, and the one genuine open question in the raw material — exactly when the patch went out — was resolved against the authoritative changelog (14:01:02 UTC) rather than Dana's unverified 2:15pm guess, which wasn't even the right time zone.
Step 2 — run the five whys without stopping early
☺ Like you're 10: "A Redis failover happened" explains what — it doesn't explain why a routine hiccup on someone else's system got to take your login page down for half an hour. Keep asking.
- Start from the timeline's first real symptom — error ratio crossing the alert threshold at 14:02 — and ask "why" of your own answer, repeatedly, the way postmortems & blameless culture lays out.
- Watch for the specific trap this incident sets: "a Redis failover during a maintenance window" is a true, complete-sounding sentence, and it is not a systemic root cause — it's an external event. A well-tolerated dependency doesn't get to become a 31-minute customer-facing outage just because it hiccuped; something on identity-api's side had to be missing for that hiccup to reach users at all.
- Check the raw material for more than one independent gap. Postmortems & blameless culture is explicit that root causes are plural "deliberately" — if the timeline shows a second, separate thing that also had to be true for this to play out the way it did, it gets its own five-whys chain, not a footnote on the first one.
Write your own five-whys chain from the 14:02 symptom before opening the answer key. Then separately ask: does the raw material describe a second independent gap that deserves its own chain? (Reread Priya's last Slack message before you answer.)
See the model Root cause(s) section
Root cause 1 (primary chain). Why did requests start failing at 14:02? Because the token-cache hit ratio collapsed from 97% to 4%, so nearly every request fell through to Postgres and saturated the connection pool. Why did the hit ratio collapse? Because cache-infra's scheduled maintenance window triggered four failovers on the Redis fleet within roughly 90 seconds, and identity-api's client kept issuing lookups against connections pointed at a primary that no longer existed. (This is the point where a draft that stops is stopping too early — "a Redis failover happened" doesn't explain why it became a customer-facing outage.) Why did the client keep using dead connections instead of detecting the failover? Because identity-api's Redis connection pool has no active health check — no periodic ping, no on-checkout validation — so a dead connection is only discovered when a live request tries to use it and times out. This is also the exact mechanism behind the 14:26:30 relapse: connections that survived the first fix as merely "idle" only failed once something finally tried to use them again, in a batch. Why was there no active health check on a pool this critical? Because reconnect-under-failover behavior was never part of identity-api's pre-production testing — there is no game-day or chaos exercise in its pipeline that actually kills the Redis primary and verifies the client recovers within an acceptable window; only normal-path functional correctness was ever tested. Why wasn't that ever required? Because identity-api's production readiness review treated Redis as infrastructure that was already someone else's problem to harden, and never asked cache-infra and core-platform to jointly verify how a dependent service behaves when that infrastructure fails over — failover testing was scoped entirely to cache-infra's own fleet, never to the services sitting downstream of it. Systemic root cause: identity-api's production readiness review had no requirement to test or configure reconnect behavior for its Redis dependency's failover, so a routine, well-tolerated failover event was free to become a 31-minute customer-facing outage with no client-side safety net to catch it.
Root cause 2 (secondary, contributing chain). Why did it take a page from core-platform — not cache-infra's own monitoring — to reveal that the fleet had just done four failovers in 90 seconds? Because cache-infra has no alert on failover frequency for this fleet; individual failovers are routine and expected, so nobody had ever defined "four in ninety seconds" as anomalous on cache-infra's own dashboards. Why was a burst like that never defined as anomalous? Because the fleet's alerting was designed around steady-state node health at the time it was stood up, and was never revisited once failover frequency became something that could genuinely damage a downstream client's connection pool. Contributing root cause: cache-infra had no burst-rate alert on its own failover events, so the fleet-side signal that would have let them investigate proactively — before any downstream team even noticed — simply didn't exist; they only learned about the storm because core-platform's Ops Lead paged them in. Note what this chain is not saying: it isn't "cache-infra should have caught this" as a criticism of the people on that team — it's a specific, missing piece of monitoring, which is exactly the kind of fixable gap a second root cause is supposed to surface, per postmortems & blameless culture's own guidance that real incidents rarely have just one.
Notice that the primary chain and the secondary chain both trace back to the same shape of gap — a missing verification step — on two different sides of the same team boundary. identity-api never verified its own reconnect behavior under failover; cache-infra never verified that its own failover behavior stayed within a tolerance downstream clients could survive. Neither team is at fault for the other's gap, and neither gap alone fully explains the incident — which is exactly why this postmortem needs both chains, not one chain picked as "the" root cause.
Step 3 — write action items that actually close the loop
☺ Like you're 10: "We should look into this" fixes nothing — a name, a date, and a ticket number is what makes an action item real.
- Write one action item per root-cause finding above — you should have at least four, since the primary chain surfaced three distinct gaps (no health check, no game-day test, no PRR requirement) and the secondary chain surfaced one (no burst-rate alert).
- Give every item a named owner — a real person or a specific team, never "we" or "someone" — and a real due date, not "soon" or "next quarter" as a vague phrase.
- Write each item as something that would go straight into a ticket tracker, per postmortems & blameless culture's own rule: a ticket, not a paragraph of prose promising to "look into" something.
Write your own action items now, one per finding from Step 2. Compare against the model table below — specifically check whether yours have real owners and real dates, not placeholders.
See the model Action items section
| Action item | Owner | Due | Ticket |
|---|---|---|---|
| Add active health checks (periodic ping + idle-connection eviction) to identity-api's Redis client pool so a dead connection is detected within seconds, not on next use | Dana Reyes, core-platform | 2026-08-25 | SRE-4821 |
| Add a burst-rate alert on cache-infra's Redis fleet for 3+ failovers within 5 minutes, routed to cache-infra-oncall | Priya Kapoor, cache-infra | 2026-08-18 | SRE-4822 |
| Add a failover game-day test to identity-api's pre-prod pipeline that kills the Redis primary and gates merges on client reconnect completing within an agreed SLA | Marcus Chen, core-platform SRE | 2026-09-15 | SRE-4823 |
| Update the production readiness review checklist to require joint sign-off — owning team and dependency team — on verified reconnect/failover behavior before any critical synchronous dependency ships | SRE Program Office | 2026-09-29 | SRE-4824 |
Item 3 is a direct application of chaos engineering — see chaos engineering at scale for how to run a failover game day like this safely and repeatedly rather than as a one-off fire drill; the companion drill Design a Chaos Experiment is good practice for writing the actual experiment plan. Item 4 is the kind of gap production readiness reviews exists specifically to catch before launch, not after an outage. None of these four items is "be more careful next time" — every one of them is something that changes what happens automatically the next time a dependency fails over, whether or not anyone's paying close attention that day.
Assemble the complete postmortem
☺ Like you're 10: Now staple your three pieces together with a short summary and an honest "what went well / what went poorly" — that's the whole document.
Summary, Timeline, Root cause(s), Impact, What went well, What went poorly, and Action items — the seven sections postmortems & blameless culture lays out. You've already drafted the hardest three. The rest is short: a three-sentence Summary anyone could skim, the Impact numbers Ellie already tallied, and an honest pair of "what went well / what went poorly" lists pulled straight from the tabletop drill's own five decisions — held severity correctly at T+0, escalated correctly at T+6, paged cache-infra promptly, posted comms before root cause was known — set against what didn't go well: no active health check, no game-day coverage, no burst-rate alert on cache-infra's own fleet.
See the complete assembled postmortem
Summary. identity-api returned elevated error rates for 31 minutes (14:02–14:33 UTC, 2026-08-11) after a routine Redis maintenance window triggered four failovers within ~90 seconds; identity-api's client held stale connections to the dead primary, and a reconnect fix that appeared to resolve the incident within 90 seconds was followed by a second, related spike as the rest of the stale connection pool cycled out. Three downstream teams (web-frontend, mobile-clients, payments) reported customer-visible impact.
Timeline. See Step 1's model timeline above, 14:01:02–14:33:07 UTC.
Root cause(s). See Step 2's model root-cause section above — a primary chain (no active health check on identity-api's Redis pool, no game-day test of reconnect-under-failover, no PRR requirement for it) and a contributing chain (no burst-rate alert on cache-infra's own failover events).
Impact. 1,922,000 total requests during the window; 173,000 (9.0% volume-weighted, peaking at 34%) returned 5xx; ≈2.8 of the service's 21.6-minute monthly error budget consumed (~13% of a full month, in one incident); 43 support tickets (baseline ~3); 11 new 1-star app-store reviews; three downstream teams affected.
What went well. Severity was held correctly at SEV2 during the ambiguous first six minutes, then escalated decisively to full Incident Command the moment blast radius across three teams confirmed it. cache-infra was paged the moment the fault localized outside identity-api's own boundary, without wasted time trying to debug someone else's infrastructure from the outside. An external status update went out at 14:16 acknowledging impact before root cause was known, rather than waiting for certainty. The IC held for a sustained recovery window before declaring resolved, which caught the 14:26:30 relapse instead of being caught by it.
What went poorly. identity-api's Redis connection pool had no active health check, so a failed primary wasn't detected until a live request timed out — twice, once for the original failover and once for the relapse. Reconnect-under-failover behavior was never exercised in pre-production testing. identity-api's production readiness review never required verified failover behavior for this dependency before launch. cache-infra had no alert on its own failover frequency, so the fleet-side anomaly wasn't caught proactively.
Action items. See Step 3's model table above — four items, each with a named owner, a real date, and a ticket number.
Common postmortem-writing mistakes — score your draft
☺ Like you're 10: Go back through your own draft and check it against this list — one point for every mistake you managed to avoid.
Score your own draft — the one you wrote before opening any answer key above — against the eight mistakes below. Give yourself one point for each you genuinely avoided.
| # | Mistake | What it looks like in a raw draft | The fix |
|---|---|---|---|
| 1 | Blame lands on a person | "Priya's fix only lasted 90 seconds" · "someone set the pool timeout wrong ages ago" | Name the action in neutral tense; name the systemic gap, not the person |
| 2 | Five whys stops at the first plausible-sounding answer | "Root cause: Redis failover during a maintenance window" | Ask why the failover was able to reach customers at all |
| 3 | Vague, unowned action items | "We should add better health checks at some point" | Named owner, real date, ticket number |
| 4 | Timeline mixes fact with opinion | "cache-infra dropped the ball again" written into the timeline itself | Timeline holds only verifiable events; analysis lives in Root cause(s) |
| 5 | Only one root cause reported when the material shows two | Stopping after the primary chain and never asking why cache-infra's own alerting missed the storm | Give each independent gap its own five-whys chain |
| 6 | Unquantified impact | "Some users had trouble logging in" | 1,922,000 requests, 173,000 failed, 43 tickets, 11 reviews |
| 7 | A guess transcribed as fact | "Patch went out around 2:15pm" copied straight in, unverified | Cross-check against the authoritative changelog before it goes in the doc |
| 8 | Irrelevant chatter left in | Retro-scheduling reminders, jokes about a dog on the keyboard | Cut anything that isn't an incident fact, a root cause, or an action item |
7–8: ready for Thursday's review meeting as written. 4–6: solid structure, but go back and fix specifically the rows you missed before it goes to review — don't just skim past them. 0–3: reread postmortems & blameless culture in full and redo Steps 1–3 from scratch; the gap here is usually a missing mental model about what a postmortem is for, not a lack of effort.
Spot the mistakes in this bad draft
☺ Like you're 10: Here's a paragraph that packs in almost every mistake from the list above at once — find them before you check the answer.
This is a real (if unusually dense) first-draft excerpt someone actually could have written from the raw material above. Find as many of the eight numbered mistakes in it as you can before opening the answer key.
Root cause: A Redis failover during cache-infra's maintenance window
overwhelmed identity-api. Honestly this is a bit of a repeat offender —
every time cache-infra touches Redis something breaks downstream, and
Priya's initial fix only lasted 90 seconds, so it doesn't seem like it
was fully tested before rolling out. The patch reportedly went out
around 2:15pm. Some users experienced login issues during the incident.
We should add better health checks and probably also talk to cache-infra
about their alerting at some point.
(Also — reminder, release retro moved to Thursday 3pm.)See which mistakes are in it
- #2 — "Root cause: A Redis failover..." stops at the external event instead of asking why identity-api had no defense against it.
- #1 — "a bit of a repeat offender," "every time cache-infra touches Redis," and "doesn't seem like it was fully tested" all blame a team or a person instead of naming a systemic gap.
- #7 — "reportedly went out around 2:15pm" transcribes Dana's unverified guess — and gets it wrong; the actual authoritative time is 14:01:02 UTC (10:01am EDT), not 2:15pm anything.
- #6 — "Some users experienced login issues" instead of the actual tallied numbers — 173,000 failed requests, 43 tickets, 11 reviews.
- #3 — "We should add better health checks and probably also talk to cache-infra... at some point" has no owner, no date, and isn't specific enough to become a ticket.
- #5 — only one root cause is named at all; cache-infra's own missing burst-rate alert — the contributing chain — never gets asked about.
- #8 — the retro-scheduling reminder has nothing to do with the incident and shouldn't be anywhere near this document.
Seven of the eight mistakes, in one short paragraph — which is exactly why real postmortem review meetings exist: to catch precisely this, before it becomes the permanent record of what the team decided the incident meant.
Ellie the Elephant: I've laid out every timestamp from all four sources, converted to UTC. Dana's "around 2:15pm" guess doesn't match anything — the changelog says 14:01:02.
Foxy: Good, drop the guess, keep the real time. Now — the first draft says "root cause: Redis failover." I don't believe that's where this actually ends.
Timmy the Turtle: It shouldn't. A failover is routine. Something on our side had no guardrail against it — that's five whys away, not one.
Foxy: Exactly — no active health check, no game-day test, no PRR requirement. Three gaps, one chain. And I'm not done — Priya's own message says cache-infra had no alert on their own failover burst either. That's a second chain.
Ellie the Elephant: Two root causes, then. I'll make sure both make it into the document — neither one erases the other.
Professor Owl: And notice what's not in either chain — nobody's name attached to a mistake, only a missing check attached to a fix. That's the whole discipline, written down properly.
1. Why is "Root cause: a Redis failover during a maintenance window" not an acceptable stopping point for this incident's five whys, even though it's a true statement? 2. Name the two independent root-cause chains this incident actually supports, and explain why one doesn't make the other unnecessary. 3. What three things does a real action item need that "we should add better health checks" is missing? 4. Dana's scratch notes contain a guessed timestamp ("maybe around 2:15pm?") — what should happen to a guess like that before it reaches the final postmortem, and what's the authoritative source that should have been checked instead?
Check your answers
- Because it names an external event, not a systemic gap — a routine, well-tolerated Redis failover doesn't explain, by itself, why it was able to become a 31-minute customer-facing outage. The five whys has to keep going until it reaches something identity-api itself was missing: an active health check, a game-day test, and a PRR requirement for dependency-failover behavior.
- The primary chain: identity-api's Redis client had no active health check, no game-day testing of reconnect-under-failover, and no PRR requirement for it. The secondary, contributing chain: cache-infra had no burst-rate alert on its own failover events, so the storm was only discovered because core-platform paged them in. Neither chain alone fully explains the incident — identity-api's gap let a normal failover reach customers, and cache-infra's gap meant nobody on the fleet side would have caught it proactively either way.
- A named owner (a real person or specific team, not "we"), a real due date (not "soon" or "at some point"), and enough specificity to become an actual ticket someone could be held to — "add active health checks (periodic ping + idle-connection eviction) to identity-api's Redis client pool" rather than "add better health checks."
- A guess like that must be verified against an authoritative source before it goes into the final document, not transcribed as-is. Here, that source is PagerDuty's own change-detection note, which recorded the maintenance window's actual start as 14:01:02 UTC — and Dana's guess turned out to be wrong, not just imprecise.
Same incident, three different drills: the incident-response tabletop drilled the decisions made while the fire was still burning, this page drilled writing it up afterward, and Capstone Part 4 asks you to run a comparable incident against a real, live service end to end. For the discipline behind the blameless principle itself, read postmortems & blameless culture and Etsy & the origin of blameless postmortems; for what happens when a postmortem culture is public by default, Cloudflare's public postmortem culture is worth reading next. When you're ready to close the loop the primary chain actually opened, Design a Chaos Experiment picks up exactly at action item 3 above.