Every API reference that's written by hand is out of date. Not "at risk of becoming out of date." Out of date, right now, in at least one place. I've owned developer documentation at one of the largest banks in Europe, and I did the thing every docs consultant will tell you to do: I stopped writing the reference by hand and generated it from the OpenAPI specification instead. Pipeline regenerates on release. If the spec changes, the docs change. Problem solved.
It wasn't solved. Drift came back within weeks — through a door I hadn't guarded, because I'd been treating the wrong thing as the source of truth.
The spec isn't the API. The spec is what someone typed about the API
Here's what actually happened. At our scale, the OpenAPI spec wasn't something backend engineers wrote as they coded — it was a governed contract: architects and API analysts designed it, reviewed it, froze it, and only then did backend teams build against it. That's not bureaucracy for its own sake. External partners integrate against a bank's payment API; you can't let its published contract drift on an individual engineer's whim, so the design-first process exists specifically to keep it stable and intentional.
Which is exactly what made the drift so persistent. When a team needed a new field or a widened response, going back through spec design and review was slower than shipping the feature — so they shipped against the real, running API and left the canonical spec untouched. The docs pipeline was doing its job perfectly: it faithfully generated a fresh, correct-looking reference from the one artifact everyone had agreed was the source of truth. The spec just wasn't describing the API anymore.
The obvious counter-question — I asked it myself — is: why not skip the governed-spec ceremony and just auto-export the spec from the code? Plenty of frameworks do this natively, from annotations. It sounds like it removes the problem by definition: a spec generated from code can't disagree with the code.
It removes the docs problem and reintroduces a worse one. A spec exported straight from whatever the code currently does isn't a contract — it's a live transcript of ungoverned change. Every ad hoc field a backend engineer adds under deadline pressure becomes, automatically and without review, part of the "official" API — shipped straight to partners integrated against last month's version, with nobody having asked whether the change was backward-compatible, well-named, or intentional at all. You've automated honesty. You haven't automated design. The lie doesn't disappear; it just moves from "the docs disagree with the code" to "the docs honestly describe an API nobody actually approved."
That's the real fork, and it has no automated way out: spec-first without enforcement drifts from the code; code-first without review drifts from good API design. Either direction, picked alone, just relocates where the lying happens.
This is not a documentation problem
That's the part that took me longer to admit than I'd like: neither direction of automation — docs-from-spec or spec-from-code — fixes this alone, because the actual failure sits upstream of both. My instinct, as the docs owner, was to fix it with docs tooling: better annotations, spec linting, a bot that nags people to update the YAML. All of that helps at the margin. None of it addresses the actual cause, which is a development process problem: the spec was being treated as an input to documentation, when it needed to be treated as a contract that gets updated — and reviewed — as part of building the feature, before ship, not after.
Those are two different mental models, and the gap between them is where every drifted API in the industry lives. "Update the docs" is a chore assigned to whoever remembers. "Update the contract" is part of what shipping the feature means — the same way updating the database schema is part of shipping a feature that needs a new column, not a follow-up ticket.
The fix that actually held
What eventually closed the gap wasn't a better pipeline. It was making the spec update part of the definition of done, enforced the same way code quality is enforced: a merge request that changes API behavior without a corresponding spec change doesn't pass review. Not "please update the docs" as a comment — a gate, next to the tests and the lint, owned by engineering the same way engineering owns everything else it can't ship broken.
Getting there wasn't smooth. The resistance came from an unexpected direction — not product managers, but engineering leads themselves, who read a mandatory spec review as someone else encroaching on decisions they considered theirs to make. What actually made the model stick was that the CTO backed it: once spec review had visible executive weight behind it, "I'll get to it" stopped being an acceptable answer.
Why this is worth saying to developers, not just to docs people
The uncomfortable generalization: documentation quality and product quality are not two separate outcomes of two separate disciplines. They're both downstream of the same thing — whether your team treats its interfaces as contracts or as descriptions written after the fact. A team that updates the spec as part of shipping the feature ships a more predictable API, because the discipline that keeps the docs honest is the same discipline that keeps the API from growing undocumented, inconsistent edge cases in the first place. A team that treats the spec as paperwork will eventually ship an API that not even its own engineers can describe accurately — with or without me.
Process unification isn't a documentation initiative wearing a process costume. It's the actual lever. The docs are just the first place you can see whether you're pulling it.
I build the systems that make this hold — automated generation as the visible layer, contract-first review gates as the part nobody sees. Both matter; the second one is the part most companies skip. If your "automated" docs still drift, that's usually where. DM me or find me on LinkedIn.
Top comments (0)