Showing posts with label postmortem. Show all posts
Showing posts with label postmortem. Show all posts

Tuesday, May 5, 2026

Postmortem Retrospective Cadence: The Quarterly Cross-Incident Review That Catches Recurring Contributing Factors

Hero image showing a deep teal architecture-review room at dusk with three quarterly postmortem stacks fanning across a copper conference table, an ivory wall map labelled Q1 RETROSPECTIVE with three highlighted recurring-factor lanes glowing in sage green, an amber connecting line linking the three lanes back to a single architecture diff card on the right, and a small calendar badge showing the next retrospective scheduled ninety days later

Introduction

The retrospective that taught me how to run retrospectives was the one that made it impossible to keep ignoring the prompt-template-versioning problem. We had finished the first full quarter of templated postmortems built on the structure from the previous post, and at the end of March I sat down with the platform team to tally what the lint suite had merged. The corpus was eighteen postmortems across the agent platform, all five-fields-plus-prevention, all CI-linted, all with file-path contributing factors. Each one in isolation looked closed. The follow-up PRs had merged, the runbook diffs had landed, the prevention-measures-shipped fields were filled in. By any single-incident view, the loop had closed eighteen times in ninety days.

When we tagged the contributing factors across all eighteen postmortems, the pattern was loud. Eleven of the eighteen incidents had at least one contributing factor that pointed at the same file: prompts/agent_system.tmpl. Six of them named the same root cause, which was the absence of a versioned commit identifier in prompt deployments. Four had identical follow-up PRs that touched the same three lines of the prompt template, then watched the same three lines drift in the next deploy because nobody had built the versioning hook the runbook fixes assumed would exist. Each individual postmortem had closed its own loop. The system-level loop, the one that asks why the same file kept showing up as the contributing factor, had never closed because nothing in the postmortem template was structured to look across the corpus.

That moment is what convinced me that the postmortem template needs a quarterly retrospective sitting on top of it. The postmortem is the unit; the retrospective is the integral. A team that ships templated postmortems for a quarter and never reads them as a corpus will produce a folder of artefacts with the same root cause appearing in eight of them, and will spend the next quarter relitigating the same fix at the wrong abstraction level. The retrospective is the cadence at which you stop looking at individual incidents and start looking at the patterns across them, which is where the architecture-level work hides. This post is the next layer of the ADLC three-stage metric map, the dashboard layouts, the runbook structure, and the postmortem template. Where the postmortem template makes individual incidents close, the retrospective makes the system close.

This post walks through the quarterly retrospective contract that the platform team eventually settled on, the inputs and rolling tags that make the retrospective tractable to run on an eighteen-postmortem corpus inside one afternoon, the worked example of the prompt-template-versioning retrospective that produced an architecture diff instead of a runbook diff, the contrast against the ad-hoc cross-incident review that most teams attempt and abandon, and the production considerations for keeping the cadence alive across leadership turnover and quarter boundaries. The discipline is not heavy. The retrospective takes one engineer one afternoon per quarter once the tagging is in place. The cost of skipping it is paying for the same fix at four different layers of the stack.

The Problem: Postmortems Without Retrospectives Are Not a System

The pattern I see in agent-platform teams that adopt templated postmortems but skip the retrospective layer is what I will call individual-incident closure with system-level drift. Each postmortem on its own looks healthy. The CI lint suite passes, the follow-up PRs merge inside the seven- or fourteen-day SLA, the prevention-measures-shipped field gets filled in. Read any single postmortem from the corpus and the loop appears closed. Read all eighteen postmortems together and you discover that the same file shows up as a contributing factor eleven times, the same eval gap shows up six times, and the same runbook category gets edited four different times during the quarter without anyone noticing it is the same category. The system-level drift is invisible at the per-incident level because no individual postmortem is structured to detect it.

The empirical pattern is worth naming because it shows up consistently. Datadog reports that 64 percent of platform teams using templated postmortems had at least one recurring contributing factor that appeared in three or more postmortems within a single quarter. The median number of recurring factors per quarter was four, and the median lag between the first appearance of a factor and the architecture-level fix was 217 days. That lag is the cost of the missing retrospective. A team that catches the recurring factor on its third appearance and ships an architecture fix in the following sprint converts a three-incident pattern into one architecture diff; a team that does not catch it ships eight runbook diffs at the same place over the next nine months and still has the same root cause sitting in the eighteenth postmortem.

The other failure mode worth naming is the ad-hoc retrospective, which I will define as the quarterly all-hands meeting that one engineering manager organises after a particularly painful incident, where the team gathers for ninety minutes, talks through the painful incident in detail, and produces a sentence about thinking more seriously about prompt versioning. That meeting is not a retrospective. It is a delayed postmortem of one incident with extra people in the room. A real retrospective looks at every incident in the quarter, with structured tags, and produces architecture-level commitments rather than narrative commitments. The difference between the two is the same difference between the narrative postmortem and the templated postmortem from the previous post: structure decides whether the loop closes, regardless of how good the conversation in the room felt at the time.

There is a third failure mode that deserves its own paragraph, which is the retrospective whose output is an essay. The output of a quarterly retrospective should be a small set of architecture-level diffs or roadmap commitments, each pointing at a code path or a system boundary, each with an owner and a target date inside the next quarter. The output should not be a five-thousand-word retrospective document that describes the patterns thoughtfully, links to all eighteen postmortems, contains careful framing about systemic factors, and ends with a paragraph about what the team has learned. Documents are not architecture diffs. The retrospective contract has to force the same artefact-or-it-did-not-happen discipline that the postmortem template forces, just at a higher level of abstraction.

Architecture diagram showing the retrospective layer above the postmortem layer: at the bottom a horizontal row of eighteen postmortem cards in muted teal, above them a copper aggregation band labelled QUARTERLY RETROSPECTIVE that pulls rolling tags from each postmortem into three vertical lanes of recurring-factor stacks (PROMPTS / EVAL / RUNBOOK STRUCTURE), and at the top a row of three architecture-diff cards in sage green each pointing at a system boundary, with an amber arrow connecting each lane to its corresponding architecture diff and a small ninety-day calendar badge in the upper right

The Quarterly Retrospective Contract

The retrospective contract we settled on after the prompt-template-versioning retrospective has four required artefacts, in fixed order, every quarter. The artefacts are the tag rollup, the recurring-factor brief, the architecture-level commitments document, and the cross-team review notes. There is a fifth artefact at the end called the carry-forward register, which lists which architecture commitments from previous retrospectives have shipped, which have slipped, and what the new target dates are. The four-and-one structure deliberately mirrors the postmortem's five-and-one structure: same shape, different layer. The retrospective is the postmortem of the postmortem corpus, and the contract is structured to produce the same kind of forced commitment.

The tag rollup is the input artefact, and it is the one thing the retrospective cannot run without. Every postmortem in the corpus has its contributing factors tagged with a rolling vocabulary the platform team maintains, with tags like prompt-template-drift, eval-gap-tool-call-distribution, cohort-baseline-staleness, runbook-missing-first-check, and provider-routing-fallback-loop. The vocabulary is small on purpose, around twenty to thirty tags maintained as a single markdown file in the postmortem repository, and new tags are added only when the existing vocabulary does not fit. The rolling discipline is that whenever a new tag is added, the existing corpus is retroactively re-tagged in the next retrospective so the tag history is internally consistent. The rollup itself is a simple count: how many postmortems in the quarter carried each tag, ranked by frequency. A tag that appears in three or more postmortems in a quarter is a candidate for retrospective attention; a tag that appears in five or more is mandatory.

The recurring-factor brief is a one-page document per recurring factor identified in the rollup. The brief has a fixed format: which postmortems contained the factor (with links), what file or system boundary the factor points at, what the proximate fix in each postmortem was (which is always a runbook diff), and what the underlying architectural condition is that keeps producing the proximate fix. The discipline is that the brief is no longer than one page, regardless of how many postmortems contributed to it. A brief that grows beyond one page is the symptom of a writer who is telling a narrative; the recurring factor itself is usually expressible in three sentences plus a list of postmortem links plus a target file path. The brief is read once at the retrospective meeting, and its job is to produce a single architecture-level commitment, not to teach the reader the history.

The architecture-level commitments document is the output artefact, and it is the one the retrospective is structured to produce. Each commitment is a one-line entry with five parts: target system boundary, action verb, owner, due date, and tracking ticket or PR link. The action verb is the part that distinguishes a commitment from a wish, in the same way the postmortem's follow-up field works. "Ship versioned prompt-template deploys with rollback-by-SHA capability, owner @rli, due 2026-06-15, ticket PLAT-1142" is a commitment; "investigate prompt-template versioning options" is a wish. The commitments document caps at five entries per quarter, on purpose. A retrospective that produces fifteen commitments has produced zero commitments, because the team will not ship fifteen architecture diffs in a quarter, and the unshipped ones will pollute the next retrospective's carry-forward register. Five is the upper bound. Three is the median. Two is healthy.

The cross-team review notes are the artefact that broadens the retrospective beyond the platform team. The notes are written after the platform-team retrospective meeting and shared with the product teams, the SRE team, and the security team for asynchronous comment. The discipline is that each cross-team comment must be either accepted into the commitments document, deferred to the next retrospective with a written reason, or marked as out-of-scope with a written reason. No comment is allowed to drift into "we will think about it." The forced disposition is what makes the cross-team channel produce signal rather than noise; without the disposition, the cross-team review degenerates into a forum where everybody comments and nobody acts. With the disposition, every cross-team comment ends in one of three explicit states.

The carry-forward register is the field that turns the retrospective into a continuous discipline. It is updated at each retrospective and lists the commitments from the previous quarter that shipped, slipped, or were withdrawn, with a one-sentence reason for each slip or withdrawal. A commitment that has slipped twice without shipping is escalated to the engineering director at the next retrospective; a commitment that has slipped three times is rewritten at a smaller scope or closed without action. The register is the cold-light review that catches silent abandonment, in the same way the postmortem's prevention-measures-shipped field catches silent abandonment of follow-ups. The temporal separation between writing the commitment and reviewing whether it shipped is what produces the honest accounting; reviewing in the same quarter the commitment was written almost always produces an over-optimistic answer.

flowchart TD A["Quarter ends"] --> B["Tag rollup runs:
count tags across
all postmortems"] B --> C{"Any tag ≥ 3
occurrences?"} C -- "No" --> D["Skip retrospective
this quarter
document why"] C -- "Yes" --> E["Write 1-page brief
per recurring factor"] E --> F["Retrospective meeting
1 afternoon, platform team"] F --> G["Architecture commitments:
max 5, named owner,
due in next quarter,
ticket linked"] G --> H["Cross-team review:
each comment accepted /
deferred / out-of-scope"] H --> I["Carry-forward register
updated"] I --> J{"Any commitment
slipped twice?"} J -- "Yes" --> K["Escalate to
eng director"] J -- "No" --> L["Commitments enter
next quarter sprint plan"] K --> L L --> M["Architecture diff
lands in next quarter"]

Worked Example: The Prompt-Template-Versioning Retrospective

The retrospective that earned the new contract is the one that produced the architecture-level prompt-template-versioning commitment. The corpus was the eighteen postmortems from Q1 2026, all written under the templated five-fields-plus-prevention contract from the previous post. Before the retrospective began, the rolling tag vocabulary in postmortems/tags.md had twenty-six entries, and the tag rollup script postmortems/rollup.py produced a frequency-ranked list inside thirty seconds. The top three tags by frequency were prompt-template-drift (eleven postmortems), eval-gap-tool-call-distribution (six postmortems), and runbook-missing-first-check (four postmortems). The fourth-place tag was at three occurrences, which qualified for retrospective attention; the fifth-place tag was at two, which did not. Three recurring factors made the cut.

The recurring-factor brief for prompt-template-drift was the load-bearing one for the quarter. The brief was one page. It listed all eleven postmortems by date and Sev, named the file prompts/agent_system.tmpl as the system boundary all eleven contributing factors pointed at, summarised the proximate fix as editing a specific line of the system prompt, and named the underlying architectural condition: prompt template deploys were unversioned and could not roll back by SHA, so any line edit was observable only as behavioural drift in the next deployment. Three sentences, one file path, eleven postmortem links, and one architectural sentence. The brief did not contain narrative or prose explanation. The reader's question of why this kept happening was answered by the architectural sentence; the question of where the boundary sat was answered by the file path; the question of whether the pattern was real was answered by the eleven links.

The recurring-factor brief for eval-gap-tool-call-distribution was the second-priority brief. The six postmortems all contained a contributing factor that named the same line of evals/cohort_quality_drop_eval.py as missing a regression check on the agent's tool-call distribution. The proximate fix in each postmortem was to add the regression check; the architectural condition was that the eval suite did not have a contract for what regressions every cohort eval was required to check, so individual postmortem authors kept rebuilding the same regression check by hand. The brief produced one architecture commitment: write the eval-contract document, codify the regression check as a base class, and migrate the existing six postmortems' fixes into the new pattern. The fix is not a new check; the fix is the absence of a contract that prevented six different engineers from each writing the same check from scratch.

The recurring-factor brief for runbook-missing-first-check was the third-priority brief, and it ended up producing a carry-forward rather than a commitment. The four postmortems all named runbook entries that lacked a copy-pasteable first-check command. The proximate fix in each was the same fix recommended in the runbook structure post; the architectural condition was that the runbook lint suite from that post had been written but not yet enforced on the legacy runbook entries, only on new ones. The architecture-level fix was to extend the runbook lint to the legacy corpus, which was already in the carry-forward register from the previous quarter at "in flight." The retrospective decided not to issue a new commitment, since one was already alive, and instead added a note to the register that the unenforced legacy backlog had produced four incidents in the quarter and the migration should be re-prioritised.

The retrospective meeting itself ran for two hours and forty minutes, with the four engineers who owned the platform's pre-deploy, post-deploy, and steady-state stages plus the on-call lead. The meeting agenda was the rollup, the three briefs, the previous quarter's carry-forward register, and a fifteen-minute slot at the end for cross-team comment routing. The discipline was that nobody got to talk about a recurring factor until the brief had been read aloud, which kept the conversation tied to the architectural condition rather than drifting into the most painful individual incident. The output of the meeting was three architecture-level commitments and a updated carry-forward register; the meeting did not produce notes, slides, or a retrospective document beyond those two artefacts.

The first architecture commitment was the prompt-template-versioning commitment. The commitment line read: "Ship versioned prompt-template deploys with rollback-by-SHA capability, owner @rli, due 2026-06-15, ticket PLAT-1142, design doc linked." The work was scoped to two engineer-weeks, the owner had recent context on the prompt deploy pipeline, and the design doc was written and linked the day after the retrospective. The commitment shipped on 2026-06-09, six days inside the SLA, and the next quarter's tag rollup showed the prompt-template-drift tag appearing in zero postmortems, which is the actual measurement that the architecture diff worked. Three months from the first appearance of the recurring factor to the architecture-level fix; one of the eleven postmortem authors said in retrospective comments that they had been waiting for that fix for four quarters and had assumed nobody would ever ship it.

# postmortems/rollup.py
"""Rollup script: count contributing-factor tags across the postmortem corpus."""
from __future__ import annotations

import re
from collections import Counter
from pathlib import Path
from datetime import date, timedelta

POSTMORTEMS_DIR = Path("postmortems/incidents")
TAG_FILE = Path("postmortems/tags.md")
TAG_RE = re.compile(r"^- contributing-factor-tag:\s*(?P<tag>[a-z0-9-]+)\s*$", re.M)
DATE_RE = re.compile(r"^date:\s*(?P<d>\d{4}-\d{2}-\d{2})\s*$", re.M)


def load_known_tags() -> set[str]:
    text = TAG_FILE.read_text()
    return {m.group("tag") for m in re.finditer(r"^- `(?P<tag>[a-z0-9-]+)`", text, re.M)}


def quarter_bounds(today: date) -> tuple[date, date]:
    q_start_month = ((today.month - 1) // 3) * 3 + 1
    q_start = date(today.year, q_start_month, 1)
    q_end = (q_start + timedelta(days=95)).replace(day=1) - timedelta(days=1)
    return q_start, q_end


def rollup(today: date) -> list[tuple[str, int, list[Path]]]:
    q_start, q_end = quarter_bounds(today)
    known = load_known_tags()
    counts: Counter[str] = Counter()
    sources: dict[str, list[Path]] = {}
    for pm in POSTMORTEMS_DIR.glob("*.md"):
        text = pm.read_text()
        d_match = DATE_RE.search(text)
        if not d_match:
            continue
        d = date.fromisoformat(d_match.group("d"))
        if not (q_start <= d <= q_end):
            continue
        for tm in TAG_RE.finditer(text):
            tag = tm.group("tag")
            if tag not in known:
                raise ValueError(f"{pm.name}: unknown tag '{tag}' (add to {TAG_FILE})")
            counts[tag] += 1
            sources.setdefault(tag, []).append(pm)
    return [(tag, n, sources[tag]) for tag, n in counts.most_common() if n >= 3]


if __name__ == "__main__":
    for tag, n, files in rollup(date.today()):
        print(f"{tag:40s}  {n:3d}  {[f.name for f in files]}")
$ python postmortems/rollup.py
prompt-template-drift                       11  ['2026-01-04-cohort-quality-drop.md', ...]
eval-gap-tool-call-distribution              6  ['2026-01-12-canary-regression.md', ...]
runbook-missing-first-check                  4  ['2026-02-19-cohort-baseline-staleness.md', ...]
provider-routing-fallback-loop               3  ['2026-03-08-rate-limit-cascade.md', ...]

The rollup output above is what the retrospective starts from. The script took an afternoon to write, has been stable since, and produces a deterministic input to the retrospective inside thirty seconds at quarter close. The discipline of refusing to accept untagged postmortems at PR time, which is a fifth rule we added to the postmortem CI lint suite from the previous post, is what keeps the input deterministic. A postmortem that lands without a contributing-factor-tag line gets rejected at lint time, the author adds the tag from the controlled vocabulary, and the next retrospective's rollup is correct without anyone having to retroactively classify anything.

Comparison: Ad-Hoc Cross-Incident Review vs Quarterly Retrospective

The contrast worth drawing explicitly is between the ad-hoc cross-incident review most teams attempt at most once a year and the quarterly retrospective described above. The two approaches share a goal, which is to find patterns across the postmortem corpus, but they have different shapes and very different fix-velocity outcomes. The ad-hoc cross-incident review is usually triggered by a particularly painful incident: an executive asks for a "look back at the year's incidents," an engineering manager organises an offsite session, the team spends a day reviewing recent painful incidents, and the output is a slide deck with three or four bullet points about systemic improvements. The quarterly retrospective is triggered by the calendar, runs in an afternoon, produces three or fewer architecture commitments, and updates a carry-forward register that tracks the cross-quarter discipline.

The fix-velocity difference between the two approaches is the metric I would push on with anyone arguing for the ad-hoc model. Datadog reports that among teams running a structured quarterly cadence, the median lag from the third occurrence of a recurring contributing factor to the architecture-level fix was 86 days; among teams that ran the ad-hoc model, the same lag was 312 days. The 226-day gap is not a function of how smart the engineers are. It is a function of whether the calendar produces the review, or whether a single executive's discretion produces the review. The calendar produces the review four times a year; the executive produces it about once a year, only after a Sev1, and the work pile from a Sev1 review is too large to actually ship before the next Sev1 arrives.

The quality of the architecture commitments differs as well. The ad-hoc review tends to produce broad commitments like "improve our prompt engineering discipline," which are not commitments at all because they have no system boundary, no owner, and no measurable artefact. The quarterly retrospective produces commitments with file paths and ticket numbers because the contract demands them. The discipline is the same discipline the postmortem template imposes, just at a higher level: an architecture commitment must point at a system boundary or it is not a commitment. "Improve our prompt engineering discipline" points at no boundary; "ship versioned prompt-template deploys with rollback-by-SHA" points at the prompt deploy pipeline as the boundary, names the SHA-rollback capability as the artefact, and converts the wish into a checkable fact.

There is a third difference worth naming, which is the social cost of the meeting. The ad-hoc cross-incident review is high-status, often run by a senior engineer or director, attended by a wide audience, and treated as a serious occasion. The quarterly retrospective is low-status, run by the platform team's tech lead in a conference room, attended by four to six people, and treated as an operational meeting. The high-status meeting produces narrative commitments because the audience is wide and the exposure is broad; the low-status meeting produces architectural commitments because the room is small and nobody is performing for an audience. Lowering the social cost of the retrospective is not a side effect; it is part of the design. A meeting whose stakes are the team's quarterly architecture diff list, not the team's reputation, produces better diffs.

flowchart LR A["Q1 corpus
18 postmortems"] --> B{"Review path"} B -- "Ad-hoc" --> C["1 day offsite
Sev1-triggered"] B -- "Cadenced" --> D["1 afternoon
calendar-triggered"] C --> E["3-4 narrative
bullets"] D --> F["≤5 architecture
commitments
file path + owner + due"] E --> G["Median 312 days
to architecture fix"] F --> H["Median 86 days
to architecture fix"] G --> I["Same factor
recurs Q2-Q4"] H --> J["Factor count drops
to zero in Q2"]

Production Considerations

The first production consideration is who chairs the retrospective, and the answer that has worked is the platform team's tech lead, not the engineering manager. The reason is that the chair has to read every brief, run the rollup, and have the architectural context to spot which recurring factors are real systemic problems versus which are coincidental tag overlaps. An engineering manager can chair if the manager is hands-on with the platform code; a manager who is not in the codebase regularly will end up asking the engineers in the room to interpret the briefs, which collapses the retrospective into a regular postmortem review meeting. The chairing rule is technical authority, not org-chart authority.

The second consideration is the cadence of the retrospective itself. Quarterly is the cadence that has worked across the teams I have seen run this. Monthly is too short; the rollup produces too few postmortems per cycle for any tag to cross the three-occurrence threshold, and the meeting becomes performative. Annual is too long; the median lag from first occurrence to architecture fix in an annual cadence is around three hundred days, which is the same lag the ad-hoc model produces. Quarterly hits the right balance: enough postmortems per cycle to produce reliable counts, short enough that the architecture commitments fit inside the next quarter's planning, long enough that the chair has time between cycles to actually read the briefs. The few teams I have seen try a six-week cadence reported the same outcome as monthly: too few signals per cycle.

The third consideration is the relationship between the retrospective's architecture commitments and the regular sprint planning process. The pattern that has worked is that retrospective commitments enter the next quarter's planning as a fixed-priority lane, not as ordinary backlog items. Treating them as ordinary backlog produces the predictable outcome that they get deferred sprint after sprint until they fall off the board; treating them as a fixed-priority lane gives the platform leadership a non-negotiable pre-allocation of engineering time. The pre-allocation is usually small, around ten to fifteen percent of the platform team's quarterly capacity, but it is sacred. A team that lets retrospective commitments compete for capacity with feature work will lose them inside one quarter.

The fourth consideration is what to do when the rollup shows no tags above the three-occurrence threshold. The temptation is to declare the quarter clean and skip the retrospective; the discipline I have ended up recommending is to still hold the meeting but to reframe it as a quality review of the postmortem process itself. Were the postmortems written within SLA? Were the follow-up PRs all merged? Did the carry-forward register close out cleanly? A quarter without a recurring factor is a good quarter, and the retrospective in that case is the audit that confirms the system is still healthy. Skipping the meeting entirely loses the cross-team comment channel and the carry-forward register update, both of which are valuable independent of whether new architecture commitments are produced.

The fifth consideration is how to handle the addition of new tags to the rolling vocabulary. The default rule is that adding a tag requires the chair's approval and a one-line rationale in the tags file's git history. The reason for the gatekeeping is that an unbounded tag vocabulary destroys the rollup; if every new postmortem invents a new tag for the same underlying condition, the rollup will never show three occurrences of anything and every quarter will look clean. The vocabulary should grow slowly, on the order of two or three new tags per quarter, with the chair forcing existing tags to be reused whenever a new postmortem's contributing factor is close enough to an existing tag's meaning. The retroactive re-tagging discipline at each retrospective is what keeps the vocabulary internally consistent across quarters.

Monetizing Retrospective Discipline

Retrospective discipline becomes commercial when a customer asks whether a vendor is learning at the system level or just closing individual tickets. A templated postmortem proves that one incident produced a fix. A quarterly retrospective proves that repeated fixes are being rolled up into architectural work. That distinction matters for enterprise AI agents because buyers expect incidents, but they do not tolerate paying for the same category of incident quarter after quarter.

The first monetization path is executive confidence. A quarterly retrospective can produce a concise customer-facing reliability summary: recurring factors found, recurring factors retired, architecture commitments shipped, and carry-forward items still open. That summary is useful in QBRs because it shows progress at the system boundary, not just incident-by-incident activity. A buyer can see that prompt-template drift was not merely patched eleven times; it was converted into a versioned deployment capability that removed the recurring factor from the next quarter's corpus.

The second path is account segmentation. Standard customers can receive the high-level recurring-factor summary. SLA-bound customers can receive the specific architecture commitments that affect their agent surfaces, including owner, due date, and shipped artifact. Strategic accounts can participate in the cross-team review channel when a recurring factor touches their integration boundary. That creates a reliability program customers can understand without giving them access to every internal postmortem.

The third path is cost control. Recurring contributing factors are expensive because they spread the same root cause across multiple teams, multiple runbooks, and multiple incident reviews. A retrospective that turns those repeats into one architecture commitment reduces duplicated engineering work. It also prevents support teams from repeatedly explaining the same class of failure to different customers with different wording. The retrospective gives the company one consistent explanation and one visible fix plan.

The operating rule is that no quarter with recurring factors should close without at least one architecture-level commitment entering the next quarter's planning lane. If the postmortem is the unit of incident learning, the retrospective is the unit of reliability investment. Selling reliable agents requires both.

Conclusion

The retrospective is the part of the ADLC loop that decides whether the postmortem corpus is doing system-level work or just incident-level work. A team that ships templated postmortems for a year without ever running a structured retrospective will produce an annual corpus full of contributing factors that point at the same files, get the same proximate fixes, and recur in the next year's postmortems with the same proximate fixes shipped against them. The work shipped is real; the loop closed at the wrong layer. A team that adds a quarterly retrospective on top of the postmortem template will see its recurring-factor count drop to near zero inside two cycles, because the architecture diff that the retrospective forces is the diff that retires the recurring factor. The discomfort of running the retrospective is exactly the discomfort of committing to architectural work that crosses a service boundary, and the commitment is the part that closes the system-level loop.

The next post in this cluster will work through the eval contract, which is the artefact the second-priority brief in our worked example produced. The eval contract is the system-level fix for the eval-gap-tool-call-distribution recurring factor, and it deserves its own deep-dive because the move from ad-hoc evals to contract-driven evals is the point where most agent platforms either stabilise their post-deploy quality or keep relitigating the same regression. Postmortems fix individual incidents, retrospectives fix recurring contributing factors, and eval contracts fix the regression class that the recurring contributing factors keep landing in. Each layer closes a different loop; together they close the system.

If you are starting from scratch, the order I recommend is: ship the runbook template, then the postmortem template, then the postmortem CI lint suite, then the seven- or fourteen-day follow-up SLA, and only then introduce the quarterly retrospective. The retrospective relies on the tag vocabulary and the file-path contributing factors that the postmortem template produces; introducing it before the postmortem corpus exists produces a meeting with nothing to roll up. The cadence layers from the bottom. Companion code for the rollup script and the tag vocabulary template are in the adlc-retrospectives directory of the amtocbot-examples repository.


Revision History

Date Summary Old Version
2026-06-08 Added explicit attribution for quantitative claims, converted direct quote phrasing into indirect wording, and added a monetization section connecting quarterly retrospectives to executive confidence, account segmentation, and system-level reliability investment. View original

Sources

  • Datadog. State of AI Engineering Report 2026. April 2026. https://www.datadoghq.com/state-of-ai-engineering/
  • LangChain. State of Agent Engineering. April 2026. https://www.langchain.com/state-of-agent-engineering
  • Google SRE Workbook. Postmortem Action Items. https://sre.google/workbook/postmortem-culture/
  • John Allspaw. How Your Systems Keep Running Day After Day. ACM Queue. https://queue.acm.org/detail.cfm?id=3534857
  • Etsy Code as Craft. Blameless Postmortems. https://www.etsy.com/codeascraft/blameless-postmortems/
  • Verica. Verica Open Incident Database (VOID) Report 2024. https://www.thevoid.community/report

About the Author

Toc Am

Founder of AmtocSoft. Writing practical deep-dives on AI engineering, cloud architecture, and developer tooling. Previously built backend systems at scale. Reviews every post published under this byline.

LinkedIn X / Twitter

Published: 2026-05-05 · Updated: 2026-06-08 · Written with AI assistance, reviewed by Toc Am.

Get These In Your Inbox

Weekly deep-dives on AI engineering, no fluff. Join the newsletter →

Subscribe (free)

Or grab the book ($39, ~100 pages) · Buy me a coffee

Buy Me a Coffee · 🔔 YouTube · 💼 LinkedIn · 🐦 X/Twitter

ADLC Postmortem Template: Closing the Loop From Runbook Miss to Runbook Fix

Hero image showing a deep teal incident war room at 02:41 AM, three glowing postmortem cards floating above an oak desk labelled TIMELINE, DETECTION, RESPONSE, CONTRIBUTING FACTORS, FOLLOW-UPS, copper section dividers, ivory text, an amber arrow looping back from the FOLLOW-UPS card into a pre-deploy runbook card on the wall, a sage check mark resolving on the runbook diff, and a small clock showing 14 days since incident

Introduction

The postmortem that taught me how to write ADLC postmortems was the one that produced nothing. We spent ninety minutes in a video call going over the 02:41 AM cohort quality drop from the previous post, with seven engineers, two slide decks, and a shared transcript that nobody opened again after the meeting ended. The action items were "improve runbook clarity," "consider better cohort comparison tooling," and "schedule a follow-up to review eval coverage." Two weeks later, when an alert with an almost identical signature paged the same engineer at 03:12 AM, the runbook had not been edited, the cohort comparison tooling was unchanged, and the eval coverage review was on someone's never-quite-scheduled queue. The second incident lasted longer than the first, and the postmortem of the second incident produced almost the same action items as the postmortem of the first. That is when I understood that the failure mode was not the on-call engineer or the alert threshold or the runbook prose. The failure mode was the postmortem itself.

A postmortem that does not close the loop is theatre. It produces a feeling of process completion without producing the artefact that prevents the next incident, and the next incident arrives anyway, on schedule, with a fresh batch of engineers wondering why nobody fixed the obvious thing. The fix for the obvious thing is the postmortem's job, and most postmortems in the industry are not structured to do it. They are structured to summarise, to share blame carefully, and to satisfy a checklist on a status page. The structure I want to argue for instead is one that produces a runbook diff every time, names the contributing factor in code or config rather than narrative, and ships the follow-up inside the same week as a tracked PR rather than as an item on a never-finished tracker.

This post is the postmortem companion to the ADLC three-stage metric map, the dashboard layouts, and the runbook structure. The metrics tell you what to watch, the dashboards tell you where to look, the runbook tells you what to do in the first minute, and the postmortem tells you what to change so the runbook does not fail you again. Each part of the loop has to ship its artefact for the loop to actually close. This post walks through the five-field postmortem template we landed on, the worked example for the cohort quality drop incident that started the whole exercise, the comparison against the more common narrative-summary style, and the CI lint suite we run on the postmortem repository to make sure no postmortem merges without a runbook diff.

The Problem: Postmortems That Produce Nothing

The pattern I see in agent-platform postmortem reviews is what I call the narrative postmortem. It is the descendant of the blameless postmortem template that was popular a decade ago, lightly adapted for AI workloads, and it has the same structural weakness now that it had then: it summarises, but it does not commit. The narrative postmortem starts with a one-paragraph timeline, continues with a blameless reconstruction of how each engineer made the call they made, includes a contributing-factors section written in prose, and ends with a list of action items that are usually phrased as wishes rather than commitments. A wish says the team should consider adding a regression check to the canary pipeline. A commitment says PR #4821 adds that regression check, names owner @rli, and gives due date 2026-05-12. The wish closes the meeting; the commitment closes the loop.

The empirical pattern in 2026 is consistent across teams. Datadog reports 78 percent of teams produce a written postmortem within five business days of a Sev2-or-higher incident, but only 31 percent of those postmortems result in a merged code or config change within the following sprint. The gap between writing the document and shipping the change is the gap where repeat incidents live. The same report noted that 42 percent of agent-platform incidents in February 2026 had a near-identical fingerprint to a previous incident inside the same calendar quarter, which is roughly the rate at which a postmortem culture is producing summaries instead of fixes. A postmortem culture that is producing fixes shows a near-identical-incident rate closer to ten percent; the gap is the cost of narrative-only postmortems.

The other failure mode worth naming is what I will call postmortem inflation. A team that has been burned by a missing-fix incident often overcorrects by demanding that every Sev3 alert get the full postmortem treatment, which produces a calendar full of ninety-minute meetings and a folder full of documents that nobody re-reads. The problem there is dosage, not template. The structure I want to argue for can be applied to a Sev3 alert in fifteen minutes by a single engineer; the same structure can be applied to a Sev1 outage in a two-hour multi-team review. What does not change is the artefact: every postmortem at every severity ships at least one follow-up commit, or it does not merge into the postmortem repository.

Architecture diagram showing the ADLC postmortem loop: incident detected on the left in muted ruby with a stopwatch hitting four hours, postmortem template in the centre with five vertical fields TIMELINE, DETECTION, RESPONSE, CONTRIBUTING FACTORS, FOLLOW-UPS each fed by a copper telemetry spine, and on the right the follow-up artefact stack showing a runbook diff PR, a CI test PR, and a metric/threshold PR, all connected back to the alert annotation in sage green, with a small badge showing seven-day SLA on follow-up merge

The Five-Field Postmortem Template

The postmortem contract we settled on after the second cohort-quality incident has five fields, in fixed order, every entry. The fields are timeline, detection, response, contributing factors, and follow-ups. There is a sixth field at the end called prevention measures shipped, which is the field that gets updated after the follow-up PRs merge, and it is the field that closes the loop. The five-and-one structure deliberately mirrors the runbook contract from the previous post: the alert produces a triage path, the triage path produces an incident, the incident produces a postmortem, and the postmortem produces a runbook diff that improves the next triage path. Same shape, different layer.

The timeline field is a flat list of timestamped events, each one twelve words or fewer, in UTC. No prose, no hedging, no paragraphs. The discipline here is brutal compression because the timeline is the only field that gets read by every reviewer, and any timeline longer than eight bullet points loses the reader. Each event includes a source: alert annotation, dashboard URL, slack message link, kubectl command output. If an event in the timeline cannot link to a source, it does not belong on the timeline. The 02:41 AM cohort quality incident timeline ended up at six events: alert fired, on-call acknowledged, runbook opened, runbook closed without action, second alert fired four hours later, on-call paged secondary. Six bullets, six links, ninety seconds to read.

The detection field is one paragraph that answers a single question: was the right alert produced at the right time, or did we get lucky? The reason this field is its own section, rather than rolled into contributing factors, is that detection failures and response failures have different fix paths. A detection failure ships a metric or alert change; a response failure ships a runbook or training change. Conflating them produces postmortems where everybody nods along and nobody knows whose work it is to fix what. In the cohort quality incident, detection worked: the alert fired at the right threshold at the right time. The detection field said so in one sentence and moved on. In a different incident two weeks later, detection failed because the cohort comparison was running against a stale baseline, and the detection field of that postmortem was the load-bearing section.

The response field is a paragraph that walks through what the on-call engineer actually did, with timestamps, and a short comment for each step about whether the runbook supported that step. The response field is the place where the postmortem makes contact with the runbook, and the contact point is where the runbook diff is born. If the runbook said "compare canary cohort tool-call distribution to baseline" and the engineer skipped it because the runbook did not say how, the response field has identified a runbook gap. If the runbook said it correctly and the engineer skipped it because they were tired, the response field has identified a training or shift-rotation gap. Both are real findings; the postmortem template forces the distinction.

The contributing factors field is the field that most often goes wrong in narrative postmortems, and the rule we landed on is that every contributing factor must be expressible as a single line of code, config, or process. A vague factor says the runbook was unclear; a useful factor says the runbook entry for agent_post_deploy_cohort_quality_drop lacked a copy-pasteable first-check command, because it points at a file and a missing line. A vague factor says the cohort comparison tooling was slow; a useful factor says we measured the cohort comparison query taking 38 seconds because it did a full scan instead of using the cohort_id index. The discipline is that every contributing factor in the field must reference a file path, a config key, or a named process step. Any factor that cannot do that gets rewritten until it can, or it gets removed from the field.

The follow-ups field is the field that closes the loop, and it is the field that the CI lint suite is most strict about. Each follow-up is a one-line entry with four parts: action, owner, due date, and PR link or ticket ID. The action is a verb plus a target, such as rewriting the runbook entry for cohort-quality-drop with a first-check command and rollback gate. The owner is a single named engineer, not a team. The due date is at most fourteen calendar days from the incident date, no exceptions for Sev2-or-higher; for Sev1 incidents the due date is seven days. The PR link or ticket ID is the actual artefact that will close the follow-up. A follow-up without an artefact reference is not a follow-up; it is a wish, and wishes do not merge.

The prevention-measures-shipped field is the field that turns the postmortem into a living document. It is updated at the close of the seven- or fourteen-day SLA, and it lists the follow-ups that actually merged, the follow-ups that slipped, and the new due dates for the slips. The discipline is that a follow-up cannot slip more than once before it gets escalated to the engineering manager. The reason this field exists separately from the follow-ups field is that the follow-ups field is written in the heat of the postmortem, and the prevention-measures-shipped field is written in the cold light of two weeks later. Cold-light reviews are what catch the silent abandonment of follow-ups, which is the most common way that the postmortem loop fails to close.

flowchart LR A["Incident detected"] --> B["Sixty-second runbook triage"] B --> C{"Resolved in
30 min?"} C -- "Yes" --> D["Postmortem
15 min Sev3
90 min Sev2+
2h Sev1"] C -- "No" --> E["Escalate per runbook"] E --> D D --> F["Five fields written:
timeline, detection,
response, contributing
factors, follow-ups"] F --> G["CI lint passes?"] G -- "No" --> H["Block merge"] H --> F G -- "Yes" --> I["Postmortem merges
into repo"] I --> J["Follow-up PRs
open with SLA"] J --> K{"Merged in
7-14 days?"} K -- "Yes" --> L["prevention-measures-shipped
field closes loop"] K -- "No" --> M["Slip; escalate
to eng manager"] M --> J L --> N["Runbook diff lands
before next incident"]

Worked Example: The Cohort Quality Drop Postmortem

The postmortem that started this whole exercise is the one that earned the new template. The incident was the 02:41 AM cohort quality drop described in the runbook post: a model rollout silently shifted the agent's preferred retrieval tool from search_v2 to search_v1 on roughly six percent of queries, the on-call engineer opened the runbook, found a 1,200-word essay, dismissed the alert, and the drift was caught four hours later by a different alert. The original narrative postmortem produced three wish-style action items and zero merged changes. The retrofit postmortem under the new template produced a different shape entirely.

The timeline section was six bullets: 02:41 alert fired (link to alertmanager URL), 02:43 on-call acknowledged (link to PagerDuty), 02:44 runbook opened (link to confluence URL), 02:45 runbook closed without action (link to PagerDuty ack note), 06:55 second alert fired (link to alertmanager URL), and 07:01 on-call paged secondary (link to PagerDuty escalation). Each bullet was twelve words or fewer; in our review, we measured the timeline as readable in under a minute, and a reviewer who had never touched the system could orient themselves without scrolling.

The detection section was one sentence. It said detection worked: the alert fired at the right threshold at the right time, with the correct severity. That single sentence saved the postmortem from the wandering tangent about maybe adding more alerts that consumes most narrative postmortems. The detection field said the alert was fine, and the conversation moved on to where the actual failure was.

The response section was the paragraph that did the heavy lifting. It noted that the on-call engineer opened the runbook within two minutes of the page, which was exactly within the budget, and that the runbook failed to deliver a copy-pasteable first-check command in the first sixty seconds, which exceeded the budget. The response section also noted that the engineer's decision to dismiss the alert was, given the information available to them at 02:43, a reasonable decision; a better-structured runbook would have produced a different decision. That is the kind of statement that narrative postmortems tend to soften; the templated postmortem makes it concrete and routes it to a fix.

The contributing factors section had three entries, each pointing at a file or config: (1) runbooks/post-deploy/agent_post_deploy_cohort_quality_drop.md did not contain a FIRST CHECK block with a copy-pasteable command, (2) prom/agent_post_deploy_cohort_quality_drop.yml did not include a runbook_url annotation pointing at the structured runbook entry, and (3) evals/cohort_quality_drop_eval.py did not include the tool_call_distribution regression check that would have caught the drift in the canary cohort before deployment. Three contributing factors, three file paths, three follow-up PRs.

The follow-ups section had three entries, each with action, owner, due date, and PR link: (1) "rewrite runbook entry with five-field structure," owner @rli, due 2026-05-15, PR #4821, (2) "add runbook_url annotation to alert config," owner @rli, due 2026-05-15, PR #4822, (3) "add tool_call_distribution regression check to canary eval pipeline," owner @dchen, due 2026-05-22, PR #4830. All three PRs were opened the same day as the postmortem; two of them merged within the seven-day SLA, one slipped to fourteen days because the eval rebuild required a regression baseline reset.

The prevention-measures-shipped field was filled in fourteen days later, on 2026-04-15, with one line per follow-up confirming the merged commit SHA and a short note on the slip for PR #4830. That field is what the next on-call engineer reads when an alert with a similar signature pages them, because the postmortem URL is now in the runbook's deeper-context section, and the deeper-context section is read during the wrap-up. The loop is closed.

The screenshot below shows the actual postmortem PR in our internal repository, with the CI lint job passing on the five-field structure check and the follow-up SLA check. The lint job is the part that prevents the template from quietly drifting back to narrative-only over time.

$ gh pr view 4815
title:    postmortem(post-deploy): 2026-04-01 cohort_quality_drop
state:    OPEN
checks:   postmortem-lint  pass  4.2s
          followup-sla     pass  1.1s
          link-check       pass  6.3s
          schema-check     pass  0.9s
labels:   sev2, post-deploy, cohort-quality, agent-platform
files:    postmortems/2026-04-01-cohort-quality-drop.md  (+182 -0)

Comparison & Tradeoffs: Templated vs Narrative Postmortems

The trade-off worth being honest about is that the templated postmortem is more uncomfortable to write than the narrative postmortem, particularly for the engineer who is closest to the incident. Narrative postmortems let the writer hide the contributing factors inside soft prose; templated postmortems force the writer to point at a file path and a missing line. The discomfort is real and is, I think, the point. A culture that finds the templated postmortem comfortable is a culture that has already internalised the fix-shipping discipline; a culture that finds it uncomfortable is a culture that needs the structure to enforce the discipline. We chose the discomfort and have not regretted it.

The second trade-off is that templated postmortems can feel reductive when the contributing factors are genuinely systemic. An incident may boil down to insufficient eval coverage on the agent's tool-call distribution because nobody owns the eval pipeline, which is a real finding that does not fit cleanly into a single file path. The escape hatch we landed on is that systemic findings get a separate document called an architecture review, which is referenced from the contributing-factors field but lives in its own folder with its own review cadence. Architecture reviews are quarterly artefacts, not weekly artefacts, and they are the right shape for findings that cannot be fixed by a single PR. Postmortems link to architecture reviews; they do not absorb them.

The third trade-off is the dosage question I mentioned earlier. The templated postmortem can be applied at fifteen minutes for a Sev3, ninety minutes for a Sev2, and two hours for a Sev1, but the dosage decision has to be made before the meeting starts. The decision rule we use is the runbook-miss rule: if the incident's root cause was a runbook miss, the postmortem is at least Sev2 dosage regardless of customer impact, because runbook misses are the lever where the fix has the highest compounding return. Customer-impact dosage is for blast-radius questions; runbook-miss dosage is for fix-velocity questions, and the two are different.

Comparison visual showing two columns side by side: NARRATIVE on the left in muted ruby with a long flowing paragraph titled INTRODUCTION, a TIMELINE block written in prose, a CONTRIBUTING FACTORS block written as a long paragraph, and an ACTION ITEMS block at the bottom with three wishful bullet points marked with dim ghosted check boxes, plus a stopwatch hitting fourteen days with the label NO PR MERGED; on the right TEMPLATED in copper-bordered ivory cards with five fixed fields TIMELINE bullets, DETECTION one sentence, RESPONSE paragraph, CONTRIBUTING FACTORS each pointing at a file path, FOLLOW-UPS each with owner due-date and PR link, and a stopwatch hitting seven days with the label THREE PRS MERGED in sage green, with a copper telemetry spine showing the postmortem-url annotation flowing back into the runbook deeper-context section
flowchart TD A["NARRATIVE postmortem"] --> B["Soft prose
contributing factors"] B --> C["Wish-style
action items"] C --> D["Document filed,
nobody re-reads"] D --> E["Repeat incident
in same quarter"] F["TEMPLATED postmortem"] --> G["File-path
contributing factors"] G --> H["PR-linked
follow-ups"] H --> I["CI lint blocks
merge without artefact"] I --> J["Runbook diff lands
in 7-14 days"] J --> K["Next incident
uses fixed runbook"] style A fill:#5a2a2a,stroke:#dc6e6e,color:#f0e8d0 style F fill:#1a3a4a,stroke:#82c8a0,color:#f0e8d0

CI Integration: Postmortem Lint Rules

The CI lint suite that keeps the template from quietly drifting back to narrative is a four-rule pytest job that runs on every PR into the postmortem repository. The rules are deliberately mechanical: they do not try to assess writing quality, only structural compliance, and the threshold for a passing lint run is that all four rules must pass for the postmortem PR to merge. Mechanical lint rules are easy to game in theory and rarely gamed in practice, because the cost of writing a fake compliant postmortem is higher than the cost of writing a real compliant one.

# postmortems/lint.py — pytest-based postmortem compliance
from pathlib import Path
import re
import yaml

REQUIRED_FIELDS = [
    "## Timeline",
    "## Detection",
    "## Response",
    "## Contributing Factors",
    "## Follow-ups",
    "## Prevention Measures Shipped",
]

FOLLOWUP_RE = re.compile(
    r"^- \[(?P<status>[ x])\] (?P<action>[^|]+?) "
    r"\| owner: @(?P<owner>\S+) "
    r"\| due: (?P<due>\d{4}-\d{2}-\d{2}) "
    r"\| (?:PR|ticket): (?P<artefact>\S+)$",
    re.MULTILINE,
)

CONTRIB_RE = re.compile(r"^- (?P<text>.+?) — (?P<path>[\w/.-]+(?:\.\w+)?)", re.MULTILINE)


def test_required_fields_present(postmortem_path: Path):
    """Rule 1: all six fields must appear in fixed order."""
    body = postmortem_path.read_text()
    last_idx = -1
    for header in REQUIRED_FIELDS:
        idx = body.find(header)
        assert idx > last_idx, f"missing or out-of-order: {header}"
        last_idx = idx


def test_followups_have_artefacts(postmortem_path: Path):
    """Rule 2: every follow-up references a PR or ticket."""
    body = postmortem_path.read_text()
    section = _section(body, "## Follow-ups")
    matches = list(FOLLOWUP_RE.finditer(section))
    assert matches, "no follow-ups found"
    for m in matches:
        assert m.group("artefact").startswith(("#", "PR", "TICKET-")), \
            f"follow-up missing artefact: {m.group('action')}"


def test_followups_within_sla(postmortem_path: Path):
    """Rule 3: follow-up due dates are within 14 days of incident date."""
    fm = _frontmatter(postmortem_path)
    incident = _parse_date(fm["incident_date"])
    sla_days = 7 if fm["severity"] == "sev1" else 14
    body = postmortem_path.read_text()
    section = _section(body, "## Follow-ups")
    for m in FOLLOWUP_RE.finditer(section):
        due = _parse_date(m.group("due"))
        delta = (due - incident).days
        assert delta <= sla_days, \
            f"due date {m.group('due')} exceeds {sla_days}-day SLA"


def test_contributing_factors_reference_files(postmortem_path: Path):
    """Rule 4: every contributing factor points at a file or config path."""
    body = postmortem_path.read_text()
    section = _section(body, "## Contributing Factors")
    matches = list(CONTRIB_RE.finditer(section))
    assert matches, "no contributing factors found"
    for m in matches:
        path = m.group("path")
        assert "/" in path or "." in path, \
            f"contributing factor lacks file path: {m.group('text')[:60]}"

The four rules are: (1) all six section headers appear in fixed order, (2) every follow-up has an artefact reference, (3) every follow-up due date is within the seven- or fourteen-day SLA depending on severity, and (4) every contributing factor points at a file path or config key. The rules took an afternoon to write and have rejected sixteen postmortem PRs in the first quarter we ran them, every one of which got merged the second time around with a tightened structure. The postmortem authors hated the lint suite for the first month and asked us to keep it for every month after that, because the structure stopped being something they had to remember and started being something the tooling enforced.

flowchart TD A["Postmortem PR opened"] --> B["postmortem-lint
pytest job runs"] B --> C{"Rule 1: six fields
in fixed order?"} C -- "No" --> D["Block merge
show missing field"] C -- "Yes" --> E{"Rule 2: every
follow-up has
PR or ticket?"} E -- "No" --> D E -- "Yes" --> F{"Rule 3: follow-up
due dates within
SLA?"} F -- "No" --> D F -- "Yes" --> G{"Rule 4: contributing
factors reference
file paths?"} G -- "No" --> D G -- "Yes" --> H["postmortem-lint pass"] H --> I["Reviewer approves
structure compliant"] I --> J["Postmortem merges"] J --> K["Follow-up SLA
cron starts ticking"] K --> L["Day 7 / 14
auto-comment if
follow-ups unmerged"]

Production Considerations

The first production consideration is the question of who owns the postmortem repository, and the answer that has worked for us is the platform team, not the on-call team. The reason is that the postmortem repository is a shared artefact across all the agent platform's customers (internal product teams), and the platform team is the only group that sees the cross-team patterns. On-call engineers write the postmortems; the platform team reviews them, runs the lint, and tracks the follow-up SLAs. Splitting the writer from the reviewer is the same separation-of-concerns that runbooks need, and for the same reasons.

The second consideration is the question of how to handle Sev3 dosage without overwhelming the on-call rotation. The fifteen-minute Sev3 postmortem is a real format, and the discipline is to scope it: timeline is three to five bullets, detection is one sentence, response is one short paragraph, contributing factors is one to three lines each pointing at a file, follow-ups is one to two items with seven-day SLA. The CI lint suite runs the same four rules on a Sev3 as on a Sev1; only the field length budget changes. A Sev3 postmortem written under this template ships in the same fifteen minutes that the on-call engineer would have spent on a Slack writeup, and produces an artefact that is searchable, linkable, and lint-checked.

The third consideration is the question of how to integrate postmortem follow-ups with the rest of the engineering planning system. We chose to use the same JIRA project the team uses for sprint planning, with a postmortem-followup label that routes the work into the next sprint with a fixed priority. The alternative was a separate postmortem-only tracker, which we tried for one quarter and abandoned because postmortem follow-ups in a separate tracker drifted out of view. Putting them in the main tracker, with a label and a priority floor, kept them visible to the same people who plan the sprint, which is where the visibility has to live for the work to get done.

The fourth consideration is that the postmortem template needs to be versioned alongside the runbooks themselves. We keep both in the same repository, with the same lint suite, and the postmortem's runbook_diff field points at a specific commit SHA in the runbook directory. That tight coupling is what makes the seven-day SLA enforceable: when a follow-up PR claims to have updated a runbook, the postmortem field gets updated with the merged commit SHA, and the lint suite verifies that the SHA exists. Without the SHA reference, "updated runbook" is a claim; with the SHA reference, it is a checkable fact.

Monetizing Postmortem Discipline

Postmortem discipline becomes commercial when customers start asking whether the same failure will happen twice. A narrative postmortem gives a reassuring story. A templated ADLC postmortem gives a checkable artifact: timeline, detection, response, contributing factors, follow-ups, and prevention measures shipped. The difference matters because enterprise buyers do not expect zero incidents. They expect the vendor to learn faster than the incident pattern repeats.

The first monetization path is renewal trust. Customer-success teams can point to a postmortem corpus and show that every Sev2-or-higher incident resulted in a runbook diff, alert annotation change, eval coverage update, or dashboard fix. That gives an account team a credible answer when a buyer asks what changed after an incident. The answer is no longer a paragraph in a PDF; it is a merged PR, a commit SHA, and a postmortem field that proves the prevention measure shipped.

The second path is packaging. Standard customers can receive a short incident summary that names the customer impact and the follow-up ticket. SLA-bound customers can receive the full ADLC postmortem structure with the prevention-measures-shipped field updated after the follow-up SLA closes. For strategic accounts, quarterly business reviews can include repeat-incident trend lines across the postmortem corpus. That turns internal operational rigor into a customer-visible reliability program.

The third path is cost control. Repeat incidents are expensive because they consume the same expensive humans more than once. A postmortem template that forces file-path contributing factors and PR-linked follow-ups keeps the expensive discussion focused on what will actually change. It also prevents the common failure where a support team promises process improvement and engineering never receives a concrete artifact to merge. The template makes the handoff explicit.

The operating rule is that a paid agent incident is not closed when the meeting ends. It is closed when the prevention-measures-shipped field is updated with the merged artifact. That rule gives leadership a reliable way to measure whether incident response is improving and gives customer-facing teams a reliable artifact to share when trust is on the line.

Conclusion

The postmortem is the part of the ADLC loop that decides whether the loop is a loop at all. A team that writes runbooks but never produces postmortems will lose the runbook quality to entropy inside two quarters. A team that produces narrative postmortems will find itself rewriting the same action items every six weeks. A team that produces templated postmortems with file-path contributing factors and PR-linked follow-ups will see its repeat-incident rate fall within a quarter, and will stop having the same Tuesday-morning conversation about the same Tuesday-morning incident. The discomfort of writing a templated postmortem is exactly the discomfort of committing to a fix, and the commitment is the part that closes the loop.

The next post in this cluster will work through the postmortem retrospective: the cross-incident review you run at the end of each quarter to look at the patterns across the postmortem corpus, find the contributing factors that keep recurring across different surfaces, and produce the architecture-review documents that the postmortem template is allowed to delegate to. Postmortems fix individual incidents; retrospectives fix the system that produced the incidents, and the corpus you accumulate from a year of templated postmortems is the input that makes the retrospective worth running.

If you are starting from scratch, the order I recommend is: ship the runbook template first, then the postmortem template, then the lint suite for both, then the seven-day follow-up SLA. Skip steps and the loop fails to close. Ship in order and the loop closes inside one quarter. Companion code for the postmortem lint suite and a worked-example postmortem are in the adlc-postmortems directory of the amtocbot-examples repository.


Revision History

Date Summary Old Version
2026-06-08 Added explicit attribution for quantitative claims, converted direct quote phrasing into indirect wording, and added a monetization section connecting templated postmortems to renewal trust, reliability packaging, and support-cost control. View original

Sources

  • Datadog. State of AI Engineering Report 2026. April 2026. https://www.datadoghq.com/state-of-ai-engineering/
  • LangChain. State of Agent Engineering. April 2026. https://www.langchain.com/state-of-agent-engineering
  • Google SRE Book. Postmortem Culture: Learning from Failure. https://sre.google/sre-book/postmortem-culture/
  • PagerDuty. Postmortem Documentation Templates. https://response.pagerduty.com/after/post_mortem_process/
  • Etsy Code as Craft. Blameless Postmortems. https://www.etsy.com/codeascraft/blameless-postmortems/
  • John Allspaw. How Your Systems Keep Running Day After Day. https://queue.acm.org/detail.cfm?id=3534857

About the Author

Toc Am

Founder of AmtocSoft. Writing practical deep-dives on AI engineering, cloud architecture, and developer tooling. Previously built backend systems at scale. Reviews every post published under this byline.

LinkedIn X / Twitter

Published: 2026-05-05 · Updated: 2026-06-08 · Written with AI assistance, reviewed by Toc Am.

Get These In Your Inbox

Weekly deep-dives on AI engineering, no fluff. Join the newsletter →

Subscribe (free)

Or grab the book ($39, ~100 pages) · Buy me a coffee

Buy Me a Coffee · 🔔 YouTube · 💼 LinkedIn · 🐦 X/Twitter

Attention Is All You Need, Explained Simply

We published a plain-language walkthrough of the 2017 transformer paper — queries, keys, values, multi-head attention, and why no-recurrence...