# Architecture Decision Records: Entscheidungen, die man in zwei Jahren noch versteht

URL: https://www.mikebild.dev/de/blog/adr-entscheidungen-die-man-versteht/

Fünf Abschnitte reichen, um eine Architekturentscheidung haltbar zu machen: Title, Status, Context, Decision, Consequences. Michael Nygard hat dieses Format 2011 in seinem Blogpost „Documenting Architecture Decisions“ beschrieben und Architecture Decision Record genannt, kurz ADR – ein kleines, versioniertes Textartefakt, das genau eine Entscheidung samt ihrem Kräftefeld festhält. Eine Seite Markdown, mehr nicht.

Der Anlass steht bei Nygard gleich im ersten Satz: „One of the hardest things to track during the life of a project is the motivation behind certain decisions.“ Das *Was* steht im Code. Das *Warum* steht nirgends – oder es steckt in einem Slack-Thread, einer Confluence-Seite, die keiner mehr findet, oder im Kopf von jemandem, der gerade Urlaub hat. Die teuerste Frage in einem Projekt ist deshalb selten „Wie bauen wir das?“, sondern „Warum haben wir das damals eigentlich so gebaut?“. Ein Team übernimmt ein System, stößt auf eine merkwürdige Entscheidung – eine ungewöhnliche Datenbank, ein selbstgebautes Caching, ein Verzicht auf den naheliegenden Message-Bus – und niemand kann sagen, ob das Absicht war oder ein Unfall. Die Leute, die es wussten, sind längst im nächsten Projekt oder in der nächsten Firma. Übrig bleibt Code, der eine Entscheidung ausführt, deren Begründung verdunstet ist.

## Das Outcome zuerst: weniger Archäologie, schnellere Übergaben

Bevor ich über Format und Tooling rede, will ich sagen, was ADRs praktisch bringen – denn darum geht es, nicht um ein weiteres Dokumentationsritual. In den Projekten, in denen ich ADRs eingeführt habe, verkürzt sich vor allem eine Sache dramatisch: die Zeit, in der ein neues Teammitglied vom „Ich verstehe den Code, aber nicht die Logik dahinter“ zum „Ich kann hier mitentscheiden“ kommt. Onboarding wird von Ausgraben zu Nachlesen.

Der zweite Effekt ist subtiler, aber wertvoller. Wenn eine Entscheidung aufgeschrieben werden *muss*, wird sie auch bewusster getroffen. Man merkt beim Schreiben, ob man wirklich Alternativen abgewogen hat oder nur den erstbesten Weg genommen hat. Das Artefakt zwingt nicht zu mehr Bürokratie – es zwingt zu Klarheit. Und Klarheit im Moment der Entscheidung ist billiger als jede spätere Rekonstruktion.

Wichtig ist mir dabei die Abgrenzung, die Nygard selbst macht: Agile Methoden sind nicht gegen Dokumentation, sie sind gegen *wertlose* Dokumentation. Das 80-seitige Architekturhandbuch, das schon beim ersten Commit veraltet, ist wertlos. Ein einseitiges ADR, das neben dem Code liegt und mit ihm durch die Git-History wandert, ist es nicht. ADRs sind der Leichtgewicht-Kompromiss zwischen „gar nichts aufschreiben“ und „alles totdokumentieren“.

## Das Format: fünf Abschnitte, eine Entscheidung

Nygard beschreibt ADRs als „a format similar to an Alexandrian pattern“ – ein kurzer Text, der ein Kräftefeld beschreibt und *eine* Entscheidung als Antwort darauf festhält. Das Format ist bewusst minimal, und die Kürze ist kein Mangel, sondern das Feature: Kleine Dokumente werden eher aktuell gehalten als große.

So sieht ein ADR bei mir typischerweise aus. Es liegt als Markdown im selben Repository wie der Code, unter `docs/adr/`:

```markdown
# 7. Use PostgreSQL as primary datastore

Date: 2021-03-12

## Status

Accepted   <!-- proposed | accepted | superseded by ADR-0012 -->

## Context

The core service needs a transactional store. Expected load is
moderate (low thousands of writes per minute at peak). The team
has deep operational experience with PostgreSQL and none with
distributed NewSQL stores. Strong consistency is a hard requirement
for the billing path.

## Decision

We will use PostgreSQL as the primary datastore for the core service.

## Consequences

Positive: strong consistency, mature tooling, no learning curve for the team.
Negative: single-primary HA needs operational care; revisit this decision
if sustained write throughput exceeds ~5k writes/second.
```

Der Context-Abschnitt ist der eigentliche Wert. Er beschreibt das, was Nygard „balancing of forces“ nennt – die Kräfte, die auf die Entscheidung wirken: erwartete Last, Team-Skills, Konsistenzgarantien, Kosten. Wer in zwei Jahren dieses ADR liest, sieht nicht nur, *dass* PostgreSQL gewählt wurde, sondern unter welchen Annahmen. Und – das ist entscheidend – der Consequences-Abschnitt nennt sogar die Bedingung, unter der man die Entscheidung neu bewerten sollte. Das ist kein Dogma, das ist ein Denkzustand, konserviert.

Ein Punkt daran wird oft übersehen: Der Context muss die Welt *zum Zeitpunkt der Entscheidung* beschreiben, nicht die Welt von heute. Ein ADR ist eine Momentaufnahme, kein Living Document. Das führt direkt zum wichtigsten Prinzip.

## Unveränderlichkeit: ADRs werden nie überschrieben

Der häufigste Fehler, den ich sehe, wenn Teams ADRs zum ersten Mal ausprobieren: Sie behandeln ein ADR wie eine Wiki-Seite und aktualisieren es, wenn sich die Entscheidung ändert. Das zerstört den ganzen Sinn. Ein ADR ist ein Log-Eintrag, kein Zustandsobjekt.

Die Regel lautet: Ein einmal akzeptiertes ADR wird nie mehr inhaltlich verändert. Ändert sich die Entscheidung, schreibt man ein *neues* ADR, das das alte ablöst. Das alte bekommt den Status `superseded` und einen Verweis auf den Nachfolger. Die Nummerierung ist fortlaufend und wird nie wiederverwendet – 0001, 0002, 0003, auch wenn 0002 längst überholt ist. Was entsteht, ist ein Entscheidungs-*Log*: eine lückenlose Historie, die zeigt, welche Entscheidung wann galt und wodurch sie abgelöst wurde.

```
docs/adr/          # sequential, zero-padded, never renumbered
  0001-record-architecture-decisions.md
  0002-use-markdown-for-adrs.md
  0007-use-postgres-as-primary-datastore.md   # Status: superseded by 0012
  0012-switch-to-cockroachdb.md               # Status: accepted
```

Diesen Lebenszyklus kann man gut als Zustandsdiagramm denken. Ein ADR wandert von `proposed` über `accepted` – und irgendwann, vielleicht, zu `superseded`, wobei der Zeiger auf das nachfolgende ADR verweist:

```mermaid
stateDiagram-v2
    [*] --> proposed
    proposed --> accepted: PR merged
    proposed --> rejected: not adopted
    accepted --> superseded: replaced by newer ADR
    superseded --> [*]: points to successor ADR
    rejected --> [*]
```

Der Charme daran ist, dass die Git-History und die ADR-History parallel laufen. Beide stecken im selben Repo, beide wandern durch dieselben Commits. Wenn ich einen alten Commit auschecke, sehe ich die ADRs, die zu diesem Stand gehörten. Das Warum reist mit dem Code durch die Zeit.

## Flurfunk gegen Artefakt

Um zu zeigen, was ADRs eigentlich verändern, hilft ein einfacher Kontrast. Auf der einen Seite steht der Normalzustand vieler Teams: Entscheidungen entstehen in Meetings, in Chat-Threads, im Vorbeigehen an der Kaffeemaschine. Sie sind real, sie prägen die Architektur – aber sie sind nirgends greifbar. Auf der anderen Seite steht das versionierte Markdown-Artefakt, das im Repo liegt und über den Pull-Request reviewt wird.

```mermaid
flowchart LR
    subgraph Flurfunk
        A[Slack thread] --> X[lost knowledge]
        B[whiteboard photo] --> X
        C[hallway talk] --> X
        D[someone's memory] --> X
    end
    subgraph Artefakt
        E[ADR in docs/adr/] --> G[reviewed via PR]
        G --> H[versioned with the code]
        H --> I[readable in two years]
    end
```

Der Unterschied ist nicht, dass links keine Entscheidungen getroffen werden. Es werden dieselben Entscheidungen getroffen. Der Unterschied ist, ob die Begründung ein Artefakt wird oder verdunstet. Und das ist letztlich eine Frage der Reibung: Solange das Aufschreiben teurer ist als das Vergessen, wird vergessen. ADRs funktionieren, weil sie das Aufschreiben so billig machen – eine Markdown-Datei, ein Commit, fertig – dass es sich lohnt.

## Tooling: gerade genug, um nicht im Weg zu stehen

Man braucht für ADRs kein Werkzeug. Eine Textdatei und Git reichen. Trotzdem hilft ein bisschen Konvention, damit die Nummerierung und die Vorlage konsistent bleiben. Nat Pryce hat dafür `adr-tools` gebaut, ein schlankes CLI, das man sich per Homebrew installiert:

```bash
# create a new, auto-numbered ADR from the standard template
$ adr new "Use PostgreSQL as primary datastore"
# -> docs/adr/0007-use-postgres-as-primary-datastore.md

# create an ADR that supersedes an earlier one
$ adr new -s 7 "Switch to CockroachDB"
# -> docs/adr/0012-switch-to-cockroachdb.md
#    and sets ADR-0007 status to "superseded by 0012"
```

Wer eine reichhaltigere Vorlage mag, findet mit MADR – „Markdown Any Decision Records“ – ein strukturierteres Template, das explizit Platz für abgewogene Optionen lässt. Für den Einstieg empfehle ich aber fast immer die nackten fünf Nygard-Abschnitte. Man kann später verfeinern; man kann schlecht nachträglich Disziplin einführen.

Der wirkungsvollste Hebel ist ohnehin kein Tool, sondern eine Prozessgewohnheit: Eine architekturrelevante Änderung im Pull-Request wird nur gemergt, wenn das zugehörige ADR im selben PR liegt. Damit wird das ADR Teil des Reviews. Die Entscheidung wird nicht nur festgehalten, sondern im selben Moment von mindestens einer zweiten Person gegengelesen. Aus dem einsamen „Ich hab da mal was gebaut“ wird ein bewusster, geteilter Schritt.

Dass das Format tragfähig ist, ist übrigens keine Einzelmeinung. Der ThoughtWorks Technology Radar stufte „Lightweight Architecture Decision Records“ bereits im November 2017 auf *Adopt* – die höchste Empfehlungsstufe. Das ist keine Neuheit mehr, das ist etablierte Praxis.

## Wo ADRs kippen – das ehrliche Kapitel

ADRs sind kein Selbstläufer. Sie scheitern, und zwar auf drei vorhersehbare Arten.

Der erste Fehlerweg: ADRs veralten trotzdem. Wer sie nicht diszipliniert bei jeder relevanten Entscheidung schreibt, bekommt eine lückenhafte Historie. Und eine lückenhafte Historie ist gefährlicher als gar keine, weil sie Vollständigkeit vortäuscht. Wenn jemand liest „hier stehen unsere Entscheidungen“ und die entscheidende fehlt, zieht er falsche Schlüsse. Er verlässt sich auf ein Log, das lügt – nicht durch Falsches, sondern durch Weglassen. Disziplin schlägt Tooling, immer. Kein CLI und kein Template ersetzt die simple Gewohnheit, im Moment der Entscheidung kurz innezuhalten und sie festzuhalten.

Der zweite Fehlerweg: zu groß, zu spät. Sobald ADRs zu Design-Dokumenten anschwellen, sinkt die Aktualisierungsquote, und Nygards ganzer Punkt – die Kürze – geht verloren. Besonders tückisch sind post-hoc geschriebene ADRs, also Begründungen, die man Wochen nach der Entscheidung nachreicht. Sie rationalisieren nur, statt das echte Kräftefeld einzufangen. Man schreibt dann nicht mehr auf, *warum* man sich entschieden hat, sondern warum die Entscheidung im Nachhinein gut aussieht. Das ist Selbstbetrug in Markdown – und er ist schwer zu entdecken, weil ein sauber formuliertes ADR überzeugend wirkt, ganz gleich, ob es die echten Kräfte einfängt oder nur eine hübsche Fassade davor baut.

Der dritte Fehlerweg: falsche Granularität. Ohne definierten Auslöser passiert eins von zwei Dingen. Entweder wird jede Nichtigkeit ein ADR, dann ertrinkt das Signal im Rauschen. Oder niemand weiß, was „architekturrelevant“ heißt, dann wird gar nichts geschrieben. Eine grobe Schwelle, früh im Team vereinbart, hilft: Ein ADR entsteht, wenn eine Entscheidung schwer umkehrbar ist, mehrere Teams betrifft oder eine naheliegende Alternative bewusst verwirft. Alles andere ist ein Kommentar im Code, kein ADR. Diese Schwelle darf ruhig unscharf bleiben; wichtiger als die exakte Grenze ist, dass das Team überhaupt eine gemeinsame Vorstellung davon teilt.

Ein Gedanke noch, der ADRs über reine Dokumentation hinaushebt: Wer die Bedingung im Consequences-Abschnitt ernst nimmt – „revisit if write throughput exceeds 5k/s“ –, kann sie überprüfbar machen. In *Building Evolutionary Architecture* nennen Ford, Parsons und Kua das *fitness functions*: automatisierte Checks, die eine Architektureigenschaft messen. Ein ADR dokumentiert die Entscheidung, eine Fitness Function wacht darüber, dass ihre Annahme noch gilt. Beides zusammen macht aus einem toten Dokument einen lebenden Wächter.

## Fazit

ADRs lösen kein technisches Problem. Sie lösen ein Gedächtnisproblem – und Gedächtnisprobleme sind auf lange Sicht teurer als technische, weil sie sich verzinsen. Jede undokumentierte Entscheidung wird mit der Zeit zu einer kleinen Schuld: Irgendwann muss jemand mit Mühe rekonstruieren, was man in fünf Minuten hätte aufschreiben können.

Der Kern ist unspektakulär und genau deshalb tragfähig: In meiner Konvention bleibt ein angenommener Text unverändert; eine neue Entscheidung ersetzt ihn mit Verweis auf das alte ADR. So bleiben Kontext, Entscheidung und Konsequenzen versioniert neben dem Code und über den Pull-Request reviewbar. Dafür braucht es kein neues System, sondern die Disziplin, das Warum festzuhalten, solange es noch frisch ist.

Der einfachste Anfang ist das erste ADR selbst – jenes, das festhält, dass ab jetzt ADRs geschrieben werden. `0001-record-architecture-decisions.md`. Alles Weitere ergibt sich, wenn die Gewohnheit einmal da ist. Und in zwei Jahren liest das jemand, den heute noch niemand im Team kennt.

## Weiterführende Quellen

- Michael Nygard, „Documenting Architecture Decisions“ (Cognitect, 2011): https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions.html
- Martin Fowler, bliki „Architecture Decision Record“: https://martinfowler.com/bliki/ArchitectureDecisionRecord.html
- ThoughtWorks Technology Radar, „Lightweight Architecture Decision Records“ (Adopt, Nov 2017): https://www.thoughtworks.com/radar/techniques/lightweight-architecture-decision-records
- adr.github.io – Community-Sammlung zu ADRs und Tooling: https://adr.github.io/
