Jedes Architekturdiagramm, das ich je in einem Wiki gesehen habe, war falsch. Nicht dramatisch falsch. Einfach leise, schrittweise falsch. Der Service mit dem Label „Auth“ wurde vor sechs Monaten in drei Microservices aufgeteilt. Der Pfeil mit der Beschriftung „sync call“ ist jetzt asynchron über eine Queue. Die mit „PostgreSQL“ beschriftete Datenbank wurde während eines Fire Drills auf etwas anderes migriert, und niemand hat die Box aktualisiert.

Das ist keine Nachlässigkeit. Das ist Physik. Code ändert sich hunderte Male pro Woche. Dokumentation ändert sich, wenn sich jemand daran erinnert. Die Halbwertszeit eines Architekturdiagramms beträgt in etwa einen Sprint. Danach wird es zur Fiktion.

Das Ziel ist nicht, Docs zu schreiben, die niemals abweichen. Das Ziel ist es, die Abweichung zu erkennen, bevor sie den nächsten Engineer in die Irre führt.

Warum Docs schneller veralten als Code

Code hat einen eingebauten Korrekturmechanismus: Er kompiliert und besteht die Tests – oder eben nicht. Dokumentation hat keinen Compiler, keine Test-Suite, kein CI-Gate. Ein falsches Diagramm rendert perfekt. Ein veralteter ADR liest sich genauso überzeugend wie ein frischer.

Die Divergenz ist auch sozial. Engineers aktualisieren Code, weil der Build bricht. Sie aktualisieren Docs, weil sie sich schuldig fühlen. Schuldgefühl ist ein unzuverlässiger Scheduler.

Wenn ein neuer Engineer dazukommt und das Wiki liest, baut er sich ein mentales Modell vom System. Wenn dieses Modell sechs Monate alt ist, trifft er Entscheidungen, die das bestehende Chaos verstärken. Die Dokumentation, die den Onboarding-Prozess erleichtern sollte, wird zur Quelle subtiler, teurer Fehlleitungen.

Die drei Fiktionsfallen

Es gibt drei Orte, an denen Architektur-Dokumentation am schnellsten zur Fiktion wird.

Das Wiki-Friedhof. Architektur-Docs in Confluence, Notion oder SharePoint leben außerhalb des Repos. Sie haben keine Commit-History, die mit Code-Änderungen korreliert. Wenn ein Refactor einen Service löscht, überlebt die Wiki-Seite wie eine digitale Geisterstadt. Kein Build bricht. Kein Alert feuert.

Die Diagramm-Fiktion. Ein wunderschönes Diagramm, das aus Lucidchart oder draw.io exportiert und in eine README eingefügt wurde, wirkt autoritativ. Es ist aber auch ein statisches Bild. Der nächste Developer, der die Architektur ändert, muss ein Design-Tool öffnen, die Source-Datei finden, sie aktualisieren, neu exportieren und wieder einfügen. Dieser Workflow hat eine Überlebensrate von 5 %.

Das allwissende README. Das Top-Level-README, das versucht, jeden Service, jede Dependency und jeden Data Flow in einer Datei zu dokumentieren. Es wird zu einem Mega-Dokument, das niemand mehr anfassen will. Irgendwann fügt eine mutige Seele eine Note hinzu: „Dieser Abschnitt könnte veraltet sein.“ Dann ein weiterer. Dann wird das gesamte Dokument in Warn-Anführungszeichen eingewickelt und aufgegeben.

Living Documentation, die ehrlich bleibt

Die Lösung ist nicht, mehr Docs zu schreiben. Es ist, die Docs unvermeidbar zu machen.

Bewege Docs ins Repository. Wenn die Dokumentation nicht im selben Pull Request wie die Code-Änderung ist, wird sie nicht aktualisiert. ADRs, Runbooks und Decision Logs sollten in docs/architecture/ oder docs/adr/ neben dem Code leben, den sie beschreiben. Wenn ein Reviewer einen Refactor ohne Doc-Update sieht, kann er den Merge blocken.

Generiere Diagramme aus Code. Mermaid, PlantUML und Structurizr erlauben es, Diagramme in Textdateien zu definieren, die im Repo leben. Ein CI-Job rendert sie bei jedem Commit. Wenn sich die Architektur ändert, ändert sich die Diagramm-Source mit ihr. Kein Design-Tool nötig.

<!-- docs/architecture/data-flow.md -->
## Ingestion Pipeline

```mermaid
graph LR
    A[Client SDK] -->|HTTP POST| B[Ingest API]
    B -->|Pub/Sub| C[Event Consumer]
    C -->|Write| D[(ClickHouse)]

Dieses Diagramm ist in einem Diff reviewbar. Wenn die Pipeline ein neues Kafka-Topic bekommt, taucht die Änderung im selben PR auf, der den Consumer hinzufügt.

**Trenne „was“ vom „warum“.** Der Codebase beschreibt bereits, was das System tut. Comments, Funktionsnamen und Types kodieren die aktuelle Struktur. Die Dokumentation sollte sich auf das „warum“ konzentrieren – warum das System so aussieht, wie es aussieht. Genau das driftet leise vor sich hin: die Begründung hinter einer Entscheidung, nicht die Entscheidung selbst.

Architecture Decision Records erfassen das. Ein ADR ist kein Spec. Es ist eine zeitgestempelte Notiz, die sagt: „An diesem Datum, aus diesen Gründen, haben wir das gewählt. Hier sind die Constraints, die wir akzeptiert haben.“ Wenn sich die Constraints ändern, wird der ADR von einem neuen abgelöst. Der alte Eintrag bleibt als History erhalten.

## Automatisiere das „was“, schreibe das „warum“

Die ehrlichste Architektur-Dokumentation ist die, die du nicht von Hand schreibst.

OpenAPI-Specs, die aus Controller-Code generiert werden, beschreiben deine API-Oberfläche akkurat. TypeDoc, RustDoc oder Javadoc beschreiben deine internen Types. Dependency-Graphen, die von `cargo tree`, `go mod graph` oder `webpack-bundle-analyzer` generiert werden, zeigen die tatsächliche Modul-Struktur.

Für höherlevelige Architektur-Constraints fungieren automatisierte Architektur-Tests als Safety Net. In Java kann ArchUnit Regeln durchsetzen wie: „Kein Package in `domain` darf von `infrastructure` abhängen.“ In Python macht `import-linter` dasselbe. In Go kannst du einen kleinen Test schreiben, der den AST durchläuft und den Build fehlschlagen lässt, wenn ein verbotener Import auftaucht.

```java
// This test fails the build if architecture rules break.
@ArchTest
static final ArchRule domain_independence =
    noClasses()
        .that().resideInAPackage("..domain..")
        .should().dependOnClassesThat()
        .resideInAPackage("..infrastructure..");

Wenn ein Developer versehentlich das falsche Package importiert, bricht der Build sofort. Das Architektur-Dokument muss ihn nicht warnen. Der Compiler tut es.

Die Trade-offs, die niemand zugibt

Living Documentation ist nicht umsonst. Sie kostet Review-Zeit, CI-Minuten und gelegentlich Streit darüber, ob eine Änderung einen neuen ADR rechtfertigt.

Nicht jedes System braucht ein Diagramm. Ein einzelner Monolith mit drei Layern braucht kein C4-Model. Der Aufwand, generierte Docs zu pflegen, sollte proportional zum Schmerz stehen, das System falsch zu verstehen. Wenn das falsche mentale Modell einen Tag Debugging kostet, investiere eine Stunde in ein Diagramm. Wenn es fünf Minuten kostet, schreibe einen Kommentar.

Generierte Docs können auch lügen. Ein OpenAPI-Spec, der aus Code generiert wird, beschreibt jeden Endpoint – auch die internen, die du zu dokumentieren vergessen hast. Ein Dependency-Graph zeigt jeden Import – auch die, die deine Architektur verletzen. Generierte Wahrheit ist akkurat, aber nicht immer nützlich. Du brauchst immer noch menschliche Kuratierung, um das Wichtige hervorzuheben.

ADRs häufen sich. Nach zwei Jahren kannst du dreißig ADRs in docs/adr/ haben. Die meisten werden irrelevant sein. Die Lösung ist nicht, sie zu löschen. Es ist, sie klar zu markieren: status: superseded mit einem Link zum Nachfolger. Die History hat Wert. Die Verwirrung nicht.

Ein minimales Setup, das funktioniert

Du brauchst keine Dokumentationsplattform. Du brauchst drei Dinge in deinem Repo.

  1. docs/adr/YYYY-MM-DD-title.md für Entscheidungen. Benutze ein leichtgewichtiges Template:
# ADR 012: Event Storage Backend

- Status: accepted
- Date: 2026-03-15

## Context
We need durable storage for ingestion events with sub-second query latency.

## Decision
Use ClickHouse for hot storage, S3 for cold archival.

## Consequences
- Fast analytical queries on recent data.
- Complex operational footprint compared to PostgreSQL.
- Migration path defined in ADR 013.
  1. docs/architecture/*.md mit Mermaid-Diagrammen für System-Boundaries und Data Flow. Verlange ein Doc-Update im selben PR wie strukturelle Code-Änderungen.

  2. Ein Architektur-Test, der deine teuerste Invariante durchsetzt. Wenn du nur eine Regel hast, mach sie zu der, die den letzten schmerzhaften Refactor verhindert hätte. Füge mehr hinzu, während das System wächst.

FAQ

Muss ich jeden Microservice diagrammen?

Nein. Diagramme die Boundaries, an denen Teams übergeben, an denen Daten Trust Zones überqueren und an denen Failures kaskadieren. Ein Diagramm deines internen CRUD-Services ist meistens Waste. Ein Diagramm, das zeigt, welche Services das Payment Gateway aufrufen, ist meistens wertvoll.

Was, wenn mein Team bereits Confluence nutzt?

Spiegele die kritischen Docs im Repo und linke nach draußen. Die Single Source of Truth bleibt in Git. Das Wiki wird zu einer Convenience Layer. Wenn das Wiki driftet, wissen die Engineers, wo sie die echte Version finden.

Wie viele ADRs sind zu viele?

Es gibt keine Obergrenze, aber es gibt eine Lesbarkeitsgrenze. Wenn ein neuer Engineer docs/adr/ nicht in zehn Minuten überfliegen kann, um die Evolution des Systems zu verstehen, füge einen Index hinzu. Gruppiere nach Subsystem. Markiere abgelöste Einträge klar.

Was ist mit Wikis für nicht-technische Stakeholder?

Product Manager und Executives brauchen High-Level-Summaries. Generiere diese aus dem ADR-Index. Pflege keine separate Narrative. Dieselben Fakten sollten vom Source Code über die ADRs in menschliche Summaries fließen. Eine Single Source of Truth, multiple Views.

Starte mit einem ADR und einem Test

Du musst deine Dokumentationskultur nicht diese Woche komplett überholen. Nimm die letzte architektonische Entscheidung, die für Verwirrung gesorgt hat. Schreibe einen ADR, der erklärt, warum du gewählt hast, was du gewählt hast. Nimm die eine Invariante, die du gerne automatisch durchgesetzt hättest. Schreibe einen Architektur-Test, der den Build fehlschlagen lässt, wenn jemand sie verletzt.

Diese beiden Artefakte werden ehrlich bleiben, weil sie im Repo leben, in PRs gereviewt werden und entweder CI bestehen oder nicht ausgeliefert werden. Alles andere – die Wiki-Seiten, die Slide Decks, die Konferenz-Poster – ist sekundär. Nice to have. Möglicherweise nützlich. Wahrscheinlich falsch.