Resources · Platform and engineering leaders

Event-driven documentation: docs that rewrite themselves on merge

Event-driven documentation is documentation regenerated by the change that made it wrong. A merge to the default branch or an infrastructure apply fires the rewrite, and the result shows up in the same pull request as the code. No schedule, no reminder, no one remembering.

Many teams think they already do this. They have a docs folder in the repo and a CI step that builds a site. That is documentation as code, which is good. It is not event-driven, because a human still has to notice the doc is wrong and edit it.

What is event-driven documentation?

Two ideas get mashed together here, and they are worth separating.

Documentation as code means docs live in version control and ship through the same pipeline as everything else. The text is still written by a person. The pipeline only publishes it.

Event-driven documentation goes one step further. The content itself is derived from the repository, and a specific event causes it to be rederived. The doc is a function of the code. When the input changes, the output changes, and nobody had to remember.

The first one fixes where docs live. The second fixes why they go stale. A carefully maintained docs/architecture.md can still go eleven months with four commits and a typo fix as the latest change.

Which events should trigger a rewrite?

Not every event. Regenerating on every push to every branch makes noise and burns money. Pick the few events that actually change what is true about the system.

What not to trigger on: a pull request opening, a commit to a feature branch, or a comment. Pull request previews are fine as a convenience, but the published docs should describe merged reality, not a proposal.

Why is a nightly job not good enough?

Because it is wrong by lunchtime.

A 2am cron regenerates the docs, the team merges eleven changes between 9am and 5pm, and from the first merge onward the docs describe a system that no longer exists. The gap is small in hours. It is not small in consequence.

Here is the case that matters. It is 4pm, something is paging, and someone opens the architecture diagram to work out what talks to the failing service. The diagram was built at 2am. At 11am somebody merged a change that put a queue between two services. The diagram confidently shows a direct call. The engineer spends twenty minutes debugging a path that does not exist.

A diagram you cannot trust in an incident is worse than no diagram, because it costs you time while looking authoritative. Teams stop opening it. Once that happens the docs are dead, whatever the build log says.

Nightly also hides the cause. When docs change overnight, the diff is a day of work from many people. When they change on merge, the diff is one change with one author, and you know which commit moved the line.

How do you review a generated doc in a pull request?

This is the part people get wrong, so here is what it looks like.

The merge triggers a job in CI. The job reads the repository and regenerates the docs. If anything changed, it opens a pull request against the docs, or pushes a commit to the same branch, with the diff.

A reviewer does not read a regenerated document top to bottom. They read the diff, and most of the time it is boring: a service gained an endpoint, a table gained a column. Skim, approve.

The diff worth stopping on looks like this:

- payments-api  ->  ledger-db          (private subnet)
+ payments-api  ->  ledger-db          (private subnet)
+ payments-api  ->  reporting-export   (public endpoint, new)
+ TRUST BOUNDARY: payments-api now sends data to a public endpoint

That last line is the point. The new diagram is not the valuable output. A change in a trust boundary is. Someone wrote application code that sends ledger data somewhere new, the tests passed, the code review was about the function and not the network path, and the generated doc is the thing that said out loud what the change did to the system.

You can review that in thirty seconds. Keep the diff short, flag the handful of change types that need a human (trust boundaries, new external dependencies, new data stores, ownership changes) and let the rest merge without ceremony.

A word on the security reviewer's view. If you run this against infrastructure, make the read happen inside your own account. Zipper Blueprint for Engineering is designed to run in an AWS account you control for exactly this reason. A pipeline that reads your repositories and Terraform state is a pipeline with a lot of access, and the generated docs inherit that sensitivity.

What breaks first?

Ownership.

Code is easy. The repository is a single source of truth, and a parser reads it the same way every time. Service maps, dependency graphs and data flows come out consistent, and when they are wrong it is usually a bug you can fix once.

Ownership is not in the code. It lives in a CODEOWNERS file somebody updated in March, in a team directory that lags reorganisations by a quarter, and in the head of the engineer who knows that "platform" now means two different teams. Org data goes stale faster than code, and it goes stale quietly, because nothing fails when it does.

So the first generated table to rot is the one that says who owns what. Do two things. Let the doc say "owner unknown" instead of guessing, and treat each unknown as a bug in the source data rather than in the doc. A CODEOWNERS file with no entry for a new service is a finding. That is the pipeline working.

The second thing that breaks is trust in the first month. If the first three diffs contain noise, people stop reading them. Tune before you tell anyone. Run it for a week on a non-critical repository and fix what is noisy.

If you want the longer argument for why docs have to be a function of the code at all, we wrote it up in how to keep on top of AI slop. The overview of the whole category is in automated documentation: what it actually means.

Frequently asked

Is event-driven documentation the same as documentation as code? No. Documentation as code means docs are stored and shipped like code, but a person still writes them. Event-driven documentation derives the content from the repository and regenerates it when a defined event occurs, such as a merge or an infrastructure apply.

Won't regenerating on every merge create constant noise? Only if you review the whole document. You review the diff, and most diffs are one or two lines. The discipline is deciding which change types need a human, like a new trust boundary or an unowned service, and letting everything else pass.

Do I need to trigger on infrastructure changes as well as code merges? Yes, if infrastructure drifts from code at all. Terraform in the repository describes intent, and an apply or a console change describes reality. A merge-only pipeline will confidently document a network that no longer matches what is deployed.


Related: Automated documentation: what it actually means · How to keep on top of AI slop

Request access

Zipper Blueprint for Engineering does this. Tell us what you need documented and we will come back with how a first engagement would work.

No newsletter, no drip sequence — a direct reply from someone who can answer technical questions.