Why Microservices Documentation Fails
A monolith has one README and one deployment process. A microservices architecture has N READMEs and N deployment processes, each in a separate repository, each maintained by a different team, each at different levels of accuracy and completeness. The documentation problem is not about writing individual service docs — most teams do that. The problem is making the whole visible.
When developers describe microservices architectures, they often reach for terms from Sam Newman's "Building Microservices" (O'Reilly, 2015, 2021) and the more recent patterns from the microservices.io catalog (Chris Richardson). But the challenge most teams face is not architectural — it's organizational: the architecture exists in code, in deployment configs, in Slack conversations, and in the heads of the engineers who built it. There is no single place where an engineer can understand the whole system.
The documentation challenge in a microservices architecture is not "how do we write good README files?" It's:
- How does an engineer understand which services exist and what they do?
- How does a developer understand the data flows and service dependencies?
- How does an on-call engineer know which service to investigate when an incident occurs?
- How does a new team member understand the architectural decisions that shaped the current structure?
These are different questions than "what does this service do?" and they require different documentation artifacts.
The Four Artifacts for a Microservices Architecture
1. The Service Catalog
A central registry of all services: what each one does, who owns it, its current status, and where its documentation lives.
2. The System Context Diagram
A high-level diagram (C4 Level 1 / Level 2) showing the relationships between services, external systems, and the users who interact with them.
3. Per-Service Documentation
For each service: purpose, API contract, dependencies, operational runbook, and contact information.
4. The Architectural Decision Record (ADR) Collection
The history of significant architectural decisions that shaped the current structure, including decisions that were reversed.
Each of these artifacts answers a different question. Together they provide the documentation surface that makes a distributed system legible.
The Service Catalog
The service catalog is the entry point for understanding what exists.
A minimal service catalog entry:
service: payment-processor
owner: @payments-team
status: production # production | internal | deprecated | experimental
language: Go
repository: https://github.com/org/payment-processor
docs: https://wiki.company.com/payment-processor
api-spec: https://github.com/org/payment-processor/blob/main/openapi.yaml
dependencies:
- fraud-detection (sync: gRPC)
- notification-service (async: Kafka topic: payment.completed)
- postgres: payments-db
description: >
Handles payment authorization, capture, and refund flows. Integrates
with Stripe for card processing and ACH for bank transfers.
sla:
availability: 99.9%
latency-p99: 200ms
oncall: https://pagerduty.com/service/payment-processor
runbook: https://wiki.company.com/runbooks/payment-processor
The catalog can be maintained as a YAML or JSON file in a shared infrastructure repository, as a structured Notion or Confluence table, or as a specialized service catalog tool (Backstage, Cortex, Port).
The catalog is more useful than the sum of individual READMEs because it is centralized. An engineer who needs to find the service that handles notifications doesn't need to know the service is called "notification-service" — they search the catalog.
Ownership is the most important field. When something goes wrong, the first question is "who do I call?" The catalog answers this with a team reference and an on-call link.
The System Context Diagram (C4 Model)
Simon Brown's C4 model (Context, Container, Component, Code) is the de facto standard for documenting software architectures at multiple levels of detail. For a microservices architecture, the most useful levels are:
Level 1 (System Context): Who are the users? What external systems does the architecture interact with? What is the boundary of the system? This diagram has very few boxes and is understandable by non-engineers.
Level 2 (Container): What are the major deployable units (services)? How do they communicate? A "container" in C4 terminology is a deployable unit — a service, a database, a queue — not a Docker container. This is the level most useful for engineering onboarding.
Level 3 (Component): What are the major components within a single service? This level is most useful when onboarding to a specific service.
For most microservices architecture documentation needs, Level 2 is the highest-value diagram: it shows all the services, their relationships, and the communication patterns.
Diagram format:
[User]
→ [API Gateway]
→ [Auth Service] ←→ [Postgres: auth-db]
→ [Product Catalog] ←→ [Postgres: catalog-db]
←→ [Elasticsearch: search-index]
→ [Order Service] ←→ [Postgres: orders-db]
→ [Payment Processor] ←→ [Stripe]
←→ [Postgres: payments-db]
→ [Kafka: order.placed]
→ [Notification Service] → [SendGrid]
→ [Inventory Service] ←→ [Postgres: inventory-db]
→ [Analytics Sink]
Tools for maintaining C4 diagrams: Structurizr (specifically designed for C4, supports code-as-model via a DSL), draw.io / diagrams.net (free, exportable), Lucidchart, Mermaid (in Markdown, rendered by GitHub and most wikis).
The key discipline: the diagram must be maintained. A system context diagram that's 12 months out of date is worse than no diagram — it actively misleads. The update trigger: any time a new service is deployed, or an existing service relationship changes, the diagram is updated in the same PR.
Diagram-as-code: Structurizr DSL and Mermaid allow diagrams to be defined as code files in version control. This is the most maintainable approach because diagram updates can be required in PRs alongside code changes.
Per-Service Documentation
Each service needs documentation at the level that answers the questions an engineer working with the service will have. The minimum viable set:
README.md at the repository root:
- What this service does (1-2 sentences)
- Who owns it and how to contact them
- Development setup (local run instructions)
- API summary (link to full OpenAPI spec)
- Link to runbook
- Link to the service catalog entry
API Contract (OpenAPI / AsyncAPI):
For synchronous HTTP services: an OpenAPI 3.x specification. For asynchronous event-driven services: AsyncAPI for the Kafka topics, SNS topics, or event queues the service publishes to or consumes. Both specifications serve as machine-readable contracts that enable:
- Auto-generated documentation sites (Swagger UI, Redoc, AsyncAPI Studio)
- Client SDK generation
- Contract testing (Pact)
- Schema validation
Operational Runbook:
A service-specific runbook covering the most common operational scenarios: how to check service health, common alerts and their remediation, how to scale the service, how to roll back a deployment, and how to handle the specific failure modes this service is prone to.
Documenting Dependencies: The Dependency Map
The most complex documentation challenge in a microservices architecture is capturing service dependencies accurately. Dependencies include:
Synchronous dependencies: Service A calls Service B directly. If B is down, A is degraded. These are the highest-impact dependencies.
Asynchronous dependencies: Service A publishes to a Kafka topic; Services B, C, and D consume it. If B is down, messages accumulate in the topic until B recovers. Lower immediate impact but complex failure mode.
Data dependencies: Service A and Service B both read from the same database (violating microservices orthodoxy but common in practice). These are often undocumented and dangerous.
Shared infrastructure dependencies: Multiple services use the same Redis instance, Elasticsearch cluster, or S3 bucket. An infrastructure failure affects multiple services.
The dependency map can be maintained in the service catalog (as shown in the YAML above) or as a separate document. What matters is that it's accurate: an incorrect dependency map is worse than no map because it creates false confidence about blast radius during incidents.
Tools for auto-generating dependency maps: Distributed tracing systems (Jaeger, Zipkin, Tempo, Datadog APM) generate service maps automatically from trace data. These auto-generated maps are more accurate than manually maintained ones because they reflect actual traffic, not documented intentions. If the team has distributed tracing, the tracing system's service map should be the canonical dependency documentation.
The ADR Collection for Architecture-Level Decisions
A microservices architecture is the result of many architectural decisions, each made at a point in time with specific constraints. The ADR collection (see: Michael Nygard, 2011) records these decisions for engineers who weren't there when they were made.
Key architectural decisions worth recording in a microservices context:
- Why microservices rather than a monolith (or why not modular monolith as an alternative)?
- What service boundary heuristics does the team use (Domain-Driven Design bounded contexts? Conway's Law alignment? team topology)?
- What is the API communication standard (REST + OpenAPI? gRPC? GraphQL?)?
- What is the asynchronous messaging standard (Kafka? RabbitMQ? SQS)?
- How is service-to-service authentication handled (mutual TLS? JWT? API keys)?
- What is the data ownership model (each service owns its database? shared databases for which use cases?)?
- How are breaking API changes handled?
- What is the policy for shared libraries vs. duplicated code across services?
Each of these decisions has alternatives that were considered. The ADR records the decision, the alternatives, and the reasoning — so that future engineers can understand why the architecture looks the way it does and can make good decisions about how to extend it.
Making Documentation Discoverable
Architecture documentation is useless if engineers don't know it exists. Three discovery mechanisms:
The architecture overview page: A single entry-point page in the team wiki that links to: the service catalog, the system context diagram, the ADR collection, the onboarding guide for new engineers, and the links to per-service documentation for the 5-10 most critical services. This page is what new engineers are given during onboarding.
Service documentation from within services: Each service's README links to the architecture overview page. This creates a two-way navigability: from the overview, you can reach any service; from any service, you can reach the overview.
Runbooks linked from alerts: Each PagerDuty or alerting system alert links directly to the relevant runbook section. When an engineer is on-call and receives an alert at 2 AM, the first thing they see is a link to the document that tells them what to do.
Worked Example: A Backend Team's Architecture Documentation Sprint
Setup: A 20-engineer backend team at a Series B company. They have 18 services. 12 have READMEs. 4 have runbooks. There is no service catalog and no system diagram. Two engineers who built the core infrastructure are leaving in the next month.
Their plan:
Week 1 — Service Catalog: They spend 2 hours in a workshop identifying all 18 services and filling in the catalog fields for each (owner, status, repository, dependencies). The catalog is a YAML file in their infrastructure repository.
Week 2 — System Context Diagram: One senior engineer draws the Level 2 C4 diagram in Mermaid. It takes 3 hours. It's added to the wiki and committed to the infrastructure repository.
Week 3 — Runbooks for top 5 services by incident frequency: They check their PagerDuty history. The 5 services that generated the most incidents in the last year get runbooks written. The engineers who are leaving write the runbooks for the services they own.
Month 2 — Backfill: The remaining 6 READMEs and 9 runbooks are written by service owners over the month. The two leaving engineers record 2 hours of video walkthrough per service as supplementary material.
Six months later: incident resolution time is down 35% because on-call engineers find runbooks immediately. Onboarding time drops by a week. The catalog is updated with each new service (PR checklist item added).
Key Takeaways
- The service catalog is the most valuable first artifact: a central registry of what services exist, what they do, who owns them, and where their docs live solves the most common failure (not knowing what exists or who to contact).
- The Level 2 C4 diagram makes relationships visible: a system context diagram at the Container level is the artifact that gives engineers the "whole system" understanding that individual service docs can't provide.
- Diagram-as-code (Mermaid, Structurizr DSL) is the most maintainable diagram format: version-controlled diagrams can be required in PRs alongside system changes.
- Distributed tracing auto-generates more accurate dependency maps than manual documentation: if the team has tracing (Jaeger, Datadog APM), the service map it generates is more reliable than a manually maintained one.
- The architecture overview page is the discovery entry point: a single page linking the catalog, diagram, ADR collection, and runbooks ensures that new engineers and on-call engineers can find everything from one starting point.
Conclusion
Documenting a microservices architecture requires solving a different problem than documenting a single service: not "how do we write a good README?" but "how do we make a distributed system legible as a whole?" The four artifacts that answer this — service catalog, system context diagram, per-service documentation with API contracts and runbooks, and the ADR collection — each answer a distinct question that the others don't. Together they make the architecture understandable to engineers who weren't there when it was built and navigable for engineers who are dealing with it at 2 AM. The discipline that keeps them accurate is connecting documentation updates to the events that require them: the PR checklist item for system changes, the postmortem action item for runbook gaps, and the onboarding retrospective for documentation that new engineers couldn't find.
Try WebSnips free — save architectural references, design document links, and service documentation with your own context annotations, tag by service and architecture layer, and build the organized technical knowledge base that makes your distributed system's architecture legible to every engineer on the team.