ADR-Template und Beispiele: Formate zum Kopieren
Das Meeting lief seit zwei Stunden. Wir diskutierten, ob wir für einen neuen Service PostgreSQL oder MongoDB nehmen sollten. Die Argumente flogen hin und her: relationale Integrität, flexible Schemas, Vertrautheit im Team, operative Komplexität.
Dann sagte jemand: „Hatten wir nicht letztes Jahr genau diese Diskussion für den User Service?"
Stille. Hatten wir. Ein Jahr zuvor hatten wir genauso lange über dieselbe Frage gesprochen und uns für PostgreSQL entschieden. Niemand erinnerte sich an die Begründung, und der Engineer, der die Diskussion damals geleitet hatte, hatte das Unternehmen verlassen. Also führten wir dieselbe Debatte noch einmal von vorn.
Damals haben wir angefangen, Architecture Decision Records zu schreiben. Dieser Beitrag ist der Teil zum Kopieren: drei Templates, wann Sie welches verwenden, und drei unserer eigenen Entscheidungen, ausgefüllt.
Was ist ein ADR?
Ein Architecture Decision Record ist ein kurzes Dokument, das eine einzige Architekturentscheidung festhält. Kein Designdokument, das alles über ein System abdeckt, sondern genau eine Entscheidung:
- Was wir entschieden haben
- Warum wir es so entschieden haben
- Welche Alternativen wir betrachtet haben
- Welche Konsequenzen das hat
Ein ADR sollte auf ein oder zwei Seiten passen. Wird er länger, dokumentieren Sie wahrscheinlich mehr als eine Entscheidung. Der vollständige Leitfaden behandelt, wann man einen schreibt, den Lebenszyklus und die Fehler, die Teams machen; dieser Beitrag bleibt bei den Formaten.
Das minimale Template (Nygard)
Michael Nygard hat das Format, das die meisten Teams bis heute verwenden, in einem Beitrag von 2011 vorgeschlagen. Fünf Teile: ein Titel in Form einer kurzen Nominalphrase, ein Status, der Kontext („die wirkenden Kräfte"), die Entscheidung („unsere Antwort auf diese Kräfte") und die Konsequenzen („der resultierende Kontext nach Anwendung der Entscheidung"). Seine Status sind Vorgeschlagen, Akzeptiert, Veraltet und Abgelöst.
# ADR-NNNN: Kurze Nominalphrase
## Status
Vorgeschlagen | Akzeptiert | Veraltet | Abgelöst durch ADR-XXXX
## Kontext
Welche Kräfte wirken? Technisch, organisatorisch, Termine, Budget.
Seien Sie konkret: Zahlen, Randbedingungen, wer betroffen ist.
## Entscheidung
Wir werden ...
## Konsequenzen
Was einfacher wird, was schwieriger wird, worauf wir jetzt achten müssen.
Wir ergänzen einen Abschnitt: Betrachtete Alternativen, zwischen Entscheidung und Konsequenzen. Das ist der Teil, der später am meisten Zeit spart, denn die Frage, die ein Jahr später kommt, lautet selten „was haben wir gewählt?" und fast immer „warum haben wir nicht X gewählt?"
## Betrachtete Alternativen
### Option B
- Vorteile: ...
- Nachteile: ...
- Warum verworfen: ...
MADR
MADR (Markdown Architectural Decision Records) ist ein stärker strukturiertes Template, gepflegt unter adr.github.io/madr. Die aktuelle Version ist 4.0.0, veröffentlicht am 17. September 2024. Es legt Metadaten in YAML-Frontmatter ab und macht die Optionen und ihre Abwägungen zu expliziten Abschnitten statt zu Fließtext.
---
status: vorgeschlagen | abgelehnt | akzeptiert | veraltet | abgelöst durch ADR-XXXX
date: JJJJ-MM-TT
decision-makers: ...
consulted: ...
informed: ...
---
# Kurzer Titel des gelösten Problems und der gewählten Lösung
## Kontext und Problemstellung
Zwei oder drei Sätze oder eine kurze Geschichte. Idealerweise als Frage formuliert.
## Entscheidungstreiber
* Treiber 1
* Treiber 2
## Betrachtete Optionen
* Option A
* Option B
* Option C
## Entscheidungsergebnis
Gewählte Option: "Option A", weil ...
### Konsequenzen
* Gut, weil ...
* Schlecht, weil ...
### Bestätigung
Wie wir prüfen, dass die Entscheidung umgesetzt wird (Review, Test, Fitness Function).
## Vor- und Nachteile der Optionen
### Option A
* Gut, weil ...
* Schlecht, weil ...
## Weitere Informationen
Links, verwandte Entscheidungen, wann neu bewerten.
Jeder Abschnitt nach Betrachtete Optionen und Entscheidungsergebnis ist in MADR optional. Löschen Sie, was Sie nicht nutzen, statt leere Überschriften stehen zu lassen.
Y-Statement
Das Y-Statement fasst eine Entscheidung in einen einzigen Satz. Es stammt von Uwe Zdun, Olaf Zimmermann und Kollegen („Sustainable Architectural Design Decisions", IEEE Software, 2013):
Im Kontext von <Use Case oder Komponente>,
angesichts von <Anliegen oder Anforderung>,
haben wir uns für <Option> entschieden
(und gegen <andere Optionen>),
um <Qualität oder Nutzen> zu erreichen,
und akzeptieren dabei, dass <Nachteil>.
Es ist zu kurz für einen vollständigen Kontextabschnitt, und genau darum geht es. Verwenden Sie es für Entscheidungen, die keine eigene Seite verdienen, als Zusammenfassungszeile über einem längeren ADR oder als Eintragsformat in einem Entscheidungslog.
Welches Format Sie verwenden sollten
| Format | Verwenden Sie es, wenn | Achten Sie auf |
|---|---|---|
| Nygard (plus Alternativen) | Sie anfangen, oder die meisten Entscheidungen einen klaren Gewinner und ein paar verworfene Optionen haben | Kontextabschnitte, die zu Aufsätzen wachsen |
| MADR | Entscheidungen umstritten sind, mehrere Personen zustimmen müssen, oder Optionen und Treiber über ADRs hinweg vergleichbar sein sollen | Jeden optionalen Abschnitt aus Gewohnheit auszufüllen |
| Y-Statement | Kleine Entscheidungen, ein Entscheidungslog oder eine einzeilige Zusammenfassung über einem längeren ADR | Es für Entscheidungen zu nutzen, die einen echten Kontextabschnitt brauchen |
Wählen Sie eines für das Repository und bleiben Sie dabei. Gemischte Formate sind schwerer zu überfliegen, als jedes einzelne Format zu schreiben ist.
Beispiel 1: ADR-0042, PostgreSQL für den Order Service
Das ist die Entscheidung aus der Geschichte am Anfang, im Nygard-Format mit unserem Abschnitt Betrachtete Alternativen.
# ADR-0042: PostgreSQL für den Order Service verwenden
## Status
Akzeptiert
## Kontext
Der Order Service braucht persistenten Speicher für Bestelldaten. Wir
erwarten anfangs 50.000 Bestellungen pro Tag, wachsend auf 500.000
innerhalb von zwei Jahren. Bestellungen haben eine klar definierte
Struktur, brauchen aber mit der Zeit eventuell zusätzliche Metadatenfelder.
Das Team hat Erfahrung mit relationalen und dokumentenorientierten Datenbanken.
## Entscheidung
Wir verwenden PostgreSQL 15 als primäre Datenbank für den Order Service.
Wir haben PostgreSQL gewählt, weil:
- ACID-Konformität für finanzielle Bestelldaten erforderlich ist
- JSON-Spalten Schemaflexibilität für Metadaten bieten
- unser Infrastrukturteam operative Erfahrung mit PostgreSQL hat
- die Abfragemuster gut zu relationaler Modellierung passen
## Betrachtete Alternativen
### MongoDB
- Vorteile: native JSON-Speicherung, einfachere horizontale Skalierung, flexible Schemaentwicklung
- Nachteile: schwächere Konsistenzgarantien, Team weniger vertraut mit dem Betrieb,
zusätzliches Tooling für Transaktionen nötig
### DynamoDB
- Vorteile: vollständig verwaltet, minimaler Betriebsaufwand, hervorragende Skalierbarkeit
- Nachteile: Vendor Lock-in bei AWS, Abfragemuster auf Zugriff über Partition-/Sort-Key
beschränkt, Kosten bei großem Volumen schwer vorhersehbar
## Konsequenzen
### Positiv
- Starke Garantien für Datenintegrität
- Das Team kann vorhandenes PostgreSQL-Know-how wiederverwenden
- Gut verstandene Betriebseigenschaften
### Negativ
- Schemamigrationen erfordern mehr Planung als bei Dokumentenspeichern
- Horizontale Skalierung komplexer, wenn wir die Kapazität eines Knotens überschreiten
- Sharding auf Anwendungsebene nötig, wenn wir an Skalierungsgrenzen stoßen
### Risiken
- Muss eventuell neu bewertet werden, wenn das Bestellvolumen 1 Mio./Tag übersteigt
- Abfragen auf JSON-Spalten sind weniger effizient als bei nativen Dokumentenspeichern
## Verwandte Entscheidungen
- Siehe ADR-0007, warum wir Eventual Consistency akzeptieren
- Löst ADR-0003 ab, das MongoDB empfohlen hatte
Seien Sie im Kontext konkret. „Wir brauchen ACID-Konformität" hilft dem nächsten Leser weit mehr als „wir brauchen Zuverlässigkeit". Und seien Sie bei den Konsequenzen ehrlich: Keine Entscheidung ist kostenlos, und das Aufschreiben der Nachteile sagt künftigen Teams, wann es Zeit ist, sie neu zu bewerten.
Beispiel 2: ADR-0007, eventgetriebene Kommunikation, in MADR
Bei der Kafka-Entscheidung lagen mehr Optionen auf dem Tisch und mehr Personen waren beteiligt, und genau hier verdienen sich die expliziten Treiber und Optionen von MADR ihren Platz.
---
status: akzeptiert
---
# Kafka für asynchrone Kommunikation zwischen Services verwenden
## Kontext und Problemstellung
Unsere Microservices kommunizieren synchron über HTTP. Das koppelt sie
eng, und ein nicht verfügbarer Service löst kaskadierende Fehler bei
den Aufrufern aus. Wie sollen Services kommunizieren, wenn der Aufrufer
keine sofortige Antwort braucht?
## Entscheidungstreiber
* Resilienz: Der Ausfall eines Services darf andere nicht mitreißen
* Losere Kopplung zwischen Services
## Betrachtete Optionen
* Synchrones HTTP beibehalten
* Eventgetriebene Kommunikation mit Apache Kafka
## Entscheidungsergebnis
Gewählte Option: "Eventgetriebene Kommunikation mit Apache Kafka", weil sie
die Laufzeitkopplung beseitigt, die kaskadierende Fehler verursacht.
### Konsequenzen
* Gut, weil Services robuster gegenüber den Ausfällen der anderen werden
* Schlecht, weil wir von starker zu Eventual Consistency wechseln
* Schlecht, weil wir jetzt einen Kafka-Cluster betreiben
* Schlecht, weil das Team Schulung zu eventgetriebenen Mustern braucht
Status und Titel werden übernommen; die Felder date und decision-makers fehlen hier, weil der ursprüngliche Record sie nicht festgehalten hat.
Beispiel 3: ADR-0015, ein Frontend-Monorepo, als Y-Statement
Die Monorepo-Entscheidung passt in einen Satz, und dieser Satz reicht, um „warum liegt alles in einem Repo?" zu beantworten.
Im Kontext unserer 5 Frontend-Anwendungen in getrennten Repositories,
angesichts von Versionskonflikten und dem Aufwand, Packages zu veröffentlichen, um Code zu teilen,
haben wir uns für ein einziges Monorepo mit Nx entschieden
(und gegen getrennte Repos mit besserem Package-Management sowie gegen ein Monorepo ohne Nx),
um einfaches Code-Sharing und einen einzigen Pull Request zu erreichen, der geteilten Code und alle seine Nutzer aktualisiert,
und akzeptieren dabei, dass ein größeres Repository Build-Caching braucht und Anwendungen versehentlich gekoppelt werden können.
Die verworfenen Optionen tragen ihre Gründe im vollständigen Record: Getrennte Repos hätten den Koordinationsaufwand beibehalten, und ein Monorepo ohne Nx hätte die Build-Zeiten untragbar gemacht.
Wo Sie sie ablegen
Legen Sie ADRs in das Repository, das sie beschreiben, in docs/adr/ oder docs/decisions/ (Nygard schlug doc/arch/adr-NNN.md vor). Sie werden mit dem Code versioniert, tauchen im Code-Review auf und können nicht in einem Wiki verloren gehen.
Nummerieren Sie sie fortlaufend und verwenden Sie nie eine Nummer erneut. Ändert sich eine Entscheidung, schreiben Sie einen neuen ADR, der den alten ablöst, und aktualisieren Sie den Status des alten, statt die Geschichte umzuschreiben.
Der Schritt, den die meisten Teams auslassen, ist, einen ADR mit dem Teil des Systems zu verbinden, den er betrifft. In Archyl hat ein ADR die Felder von Nygard (Status, Kontext, Entscheidung, Konsequenzen) plus ein Datum und einen „abgelöst durch"-Link, und er hängt an den Systemen, Containern und Komponenten, die er geprägt hat. Wer sich den Order Service im C4-Diagramm ansieht, sieht ADR-0042 daneben: „Warum läuft dieser Service auf PostgreSQL?" ist einen Klick entfernt.
Die Fallstricke (ADRs im Nachhinein schreiben, sie auf fünf Seiten anwachsen lassen, die Praxis nach dem ersten stressigen Quartal aufgeben) behandelt der vollständige Leitfaden.
Fangen Sie mit einem an
Das zweistündige Meeting über PostgreSQL vs. MongoDB? Als die Frage das nächste Mal aufkam, war sie in zehn Minuten erledigt, weil jemand ADR-0042 gefunden hat. Die Randbedingungen, die Alternativen und die Begründung standen alle darin. Wir haben bestätigt, dass die ursprüngliche Entscheidung noch galt, und sind weitergegangen.
Wählen Sie eines der Templates oben und fügen Sie es in docs/adr/0001-record-architecture-decisions.md ein. Ihr erster ADR kann die Entscheidung sein, ADRs zu schreiben.
Mehr über Architekturdokumentation: der Leitfaden zum C4-Modell | Warum Dokumentation wichtig ist | User Flows dokumentieren