Docs & Code Guide

Keep microservices docs in sync: docs live with each service, the system view is assembled

Microservices multiply the documentation problem by the number of services: forty repos, forty READMEs, and one wall diagram that was wrong before the plotter finished printing it. The architecture that survives is federated: each service documents itself in its own repo, a catalog holds the machine-readable card per service, and the system view is generated from the catalog rather than drawn.

8 min readFor platform teams whose system diagram lists two services that no longer exist

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

234/20003 credits left
Try:

No account needed · Editable canvas, not a picture

Docs live with each service or they die

The unit of change in a microservices estate is the service repo, so the unit of documentation has to be the service repo too. A README that lives next to the code gets updated in the same pull request that changes the behavior, reviewed by the same people, and versioned with the release. A central wiki page about the same service has none of those properties: it depends on someone remembering to leave the repo and edit a page nobody reviews.

The per-service README earns its keep with four sections: what the service does, who owns it, how to run it locally, and what it depends on. Everything else, API reference, dashboards, runbooks, should be linked, not duplicated, because every duplicated fact is a future contradiction.

The catalog gives every service a machine-readable card

Prose READMEs are for humans; the estate also needs a record that tools can read. Backstage standardized the pattern with catalog-info.yaml: a small file in each repo declaring the component's name, type, lifecycle, owner, the system it belongs to, the APIs it provides and the components it depends on. The catalog ingests these files and answers the questions that otherwise require archaeology: who owns this, what depends on it, what does it depend on.

The fields that pay rent are owner and dependsOn. Owner turns every incident and deprecation into a directed message instead of a broadcast. DependsOn turns "can we retire this service" from a guess into a query.

# catalog-info.yaml, lives in the service repo, reviewed with the code
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: payments-service
  description: Charges cards and records ledger entries
  annotations:
    github.com/project-slug: acme/payments-service
spec:
  type: service
  lifecycle: production
  owner: team-payments
  system: checkout
  providesApis: [payments-api]
  dependsOn: [component:default/ledger-service]

The system view is assembled, never hand-drawn

The aggregate diagram, the one on the architecture page that shows the gateway, the services, the queues and the databases, should be a projection of the service list, not an independent artwork. When it is hand-drawn it competes with the catalog as a second source of truth and loses quietly: a new service ships, the catalog knows, the drawing does not.

The working loop: generate the first version from your service list, catalog export or a plain description with the microservices architecture diagram generator, then regenerate when the catalog changes. An agent connected to the Datadef MCP server, registry name io.datadef/mcp, can read the catalog-info files or the service list after a merge and update the diagram to match. Datadef does not watch your repos, so wire the call into the event that already fires when a service is added: the catalog registration PR. An API key, part of the paid plans, authorizes the agent.

What breaks when a service renames

A rename is the drill that reveals every unmanaged copy of your architecture. The catalog refs break loudly: any component still declaring dependsOn component:default/old-name points at nothing, and Backstage shows the dangling relation. The quiet breakage is everything outside the catalog: dashboards keyed on the old service label, alert routes, wiki links, and above all the hand-drawn diagram, which keeps the old box because no process exists to tell it otherwise.

The rename checklist that works is short because the architecture is federated: update catalog-info.yaml, let the catalog surface dangling refs from dependents, regenerate the system diagram from the updated list. What cannot be checklisted is hunting down every pasted screenshot of the old diagram, which is the argument for embedding a live view instead of pasting exports: a diagram embedded from a live URL follows the source within minutes of the edit, while every pasted copy keeps the old name forever.

Rename test

If renaming a service requires editing more than the service repo and regenerating projections, the extra edits mark your unmanaged documentation copies. Each one is future drift.

Boundaries and ownership

Two scope notes keep this honest. Datadef draws and keeps current the system view, the boxes-and-arrows level; it does not sync prose documentation or API references, which belong in the service repos and, if you run Backstage, in TechDocs, where embedding diagrams in Backstage TechDocs shows how the generated diagram and the prose meet on one page. The live embed also requires the Datadef project to be shared public; internal-only estates keep the project private and export instead.

And someone must own the assembled view. Federated docs fail at the seams: every service documented, nobody responsible for the whole. Give the system diagram an owning team, typically platform, and treat catalog changes as its update trigger. The patterns for that split are covered in documentation ownership models, and the wider code-to-docs loop in keep architecture docs in sync with code.

FAQ

How do I keep microservices documentation up to date?

Federate it. Each service keeps its README and its catalog-info.yaml in its own repo, updated and reviewed with the code. The system-level view is assembled from the catalog: generated from the service list and regenerated when the catalog changes, never hand-drawn. Central hand-maintained pages about individual services are the part that rots, so eliminate them.

What should a service catalog entry contain?

The machine-readable minimum: name, description, type, lifecycle, owner, the system it belongs to, the APIs it provides, and the components it depends on. In Backstage this is catalog-info.yaml. Owner and dependsOn are the load-bearing fields; they turn incidents and deprecations into directed questions with exact answers.

Who should own the aggregate system diagram?

A named team, usually platform or architecture, with the catalog as its trigger: when a service is added, renamed or retired, the registration change is the event that prompts regeneration. Without a named owner, federated documentation fails at exactly the system level, with every service documented and the whole undocumented.

What breaks in documentation when a service is renamed?

Catalog references break visibly, since dependsOn entries pointing at the old name dangle. Everything outside the catalog breaks silently: dashboard labels, alert routes, wiki links, and every pasted copy of the architecture diagram. Live-embedded diagrams follow the source after the edit; pasted exports keep the old name until someone notices.

Does the system diagram update itself when we add a service?

No. Datadef does not watch repositories or catalogs; the diagram updates when a person or an agent invokes the update, for example an MCP-connected agent reading the catalog in the registration PR's pipeline. What is automatic is propagation: once the diagram is edited, every live embed of it shows the new state within minutes.