Event-Driven Architecture dokumentieren mit dem C4-Modell - Archyl Blog

Event-Driven Architectures sind leistungsstark, aber notorisch schwer zu dokumentieren. Events sind unsichtbar, asynchron und designbedingt entkoppelt. Dieser Leitfaden zeigt, wie Sie das C4-Modell nutzen, um Event Flows, Event Channels und asynchrone Muster zu dokumentieren -- und wie Archyl Event-Driven-Systeme sichtbar macht.

Event-Driven Architecture dokumentieren mit dem C4-Modell

Event-Driven Architecture ist zum Standard für den Bau skalierbarer, lose gekoppelter Systeme geworden. Services publizieren Events, wenn etwas passiert. Andere Services abonnieren diese Events und reagieren. Der Publisher weiß nicht, wer zuhört. Der Subscriber weiß nicht, wer publiziert hat. Das System ist entkoppelt, resilient und flexibel.

Es ist auch nahezu unsichtbar.

Wenn Sie ein traditionelles C4-Diagramm eines Event-Driven-Systems betrachten, sehen Sie Services mit Pfeilen, die auf einen Message Broker zeigen. Service A publiziert an Kafka. Service B konsumiert von Kafka. Aber welche Events fließen zwischen ihnen? Wie sieht das Schema aus? Wer hört noch zu? Was passiert, wenn ein Consumer ausfällt? Das Diagramm zeigt die Infrastruktur, versteckt aber das Verhalten.

Event-Driven Architecture zu dokumentieren erfordert Techniken, die das Unsichtbare sichtbar machen -- die nicht nur die Infrastruktur (Broker, Queues, Topics) zeigen, sondern die Events selbst, ihre Flows, ihre Schemas und ihre Garantien. Dieser Leitfaden behandelt, wie das mit dem C4-Modell gelingt und wie Archyls Event-Channel-Features Event-Driven-Systeme zu erstrangigen Bürgern in Ihrer Architekturdokumentation machen.

Warum Event-Driven-Systeme schwer zu dokumentieren sind

Event-Driven Architecture bringt mehrere Dokumentationsherausforderungen mit sich, die in synchronen Request-Response-Systemen nicht existieren.

Unsichtbarer Kontrollfluss

In einem synchronen System können Sie einen Request vom Client zum Server verfolgen, indem Sie der Aufrufkette folgen. Service A ruft Service B auf, der Service C aufruft. Der Kontrollfluss ist explizit und im Code sichtbar.

In einem Event-Driven-System ist der Kontrollfluss implizit. Service A publiziert ein OrderCreated Event. Irgendwo reagiert Service B auf dieses Event, indem er Bestand reserviert. Woanders reagiert Service C, indem er eine Bestätigungs-E-Mail sendet. Service A weiß nichts von B oder C. Der Kontrollfluss wird durch die Event-Subscriptions definiert, nicht durch den Code des Publishers.

Diese Indirektion bedeutet, dass Sie das Verhalten des Systems nicht verstehen können, indem Sie den Code eines einzelnen Services lesen. Sie brauchen eine höhere Sicht, die die Event Flows über Services hinweg zeigt -- und genau diese Sicht sollte Architekturdokumentation bieten.

Many-to-Many-Beziehungen

In synchronen Architekturen sind Beziehungen typischerweise Eins-zu-Eins oder Eins-zu-Wenige. Service A ruft Service B auf. Die Beziehung ist direkt und durch den API-Aufruf dokumentiert.

In Event-Driven Architectures sind Beziehungen Many-to-Many. Ein einzelner Event-Typ kann einen Producer und fünf Consumer haben. Ein einzelner Service kann Events von zehn verschiedenen Producern konsumieren. Der Beziehungsgraph ist dichter und komplexer als in synchronen Systemen.

Traditionelle Architekturdiagramme kämpfen mit dieser Dichte. Einen Pfeil von jedem Producer zu jedem Consumer durch jedes Topic zu zeichnen, erzeugt ein Diagramm, das wie ein Teller Spaghetti aussieht. Sie brauchen einen Dokumentationsansatz, der Event Flows auf dem richtigen Abstraktionslevel zeigt.

Schema-Evolution

Event-Schemas entwickeln sich im Laufe der Zeit. Das OrderCreated Event könnte mit fünf Feldern beginnen und über zwei Jahre auf fünfzehn wachsen. Consumer könnten von bestimmten Feldern abhängen. Schema-Änderungen können Consumer brechen, wenn sie nicht abwärtskompatibel sind.

Das aktuelle Schema zu dokumentieren ist notwendig, aber nicht ausreichend. Sie müssen auch die Schema-Versionierungsstrategie, Kompatibilitätsgarantien und die Historie von Breaking Changes dokumentieren.

Eventual Consistency

Event-Driven-Systeme sind von Natur aus eventually consistent. Wenn Service A ein Event publiziert, verarbeitet Service B es möglicherweise Millisekunden oder Minuten später (wenn der Consumer hinterherhinkt oder Retries nötig sind). Das System befindet sich während dieses Fensters in einem inkonsistenten Zustand.

Dokumentation sollte diese Konsistenzgrenzen erfassen. Welche Teile des Systems sind strongly consistent? Welche eventually consistent? Wie hoch ist die erwartete Propagierungsverzögerung? Was passiert während des Inkonsistenzfensters?

Dead Letter Queues und Fehlerbehandlung

Wenn ein Event-Consumer eine Nachricht nicht verarbeiten kann, geht das Event typischerweise in eine Dead Letter Queue (DLQ). Aber was passiert dann? Wer überwacht die DLQ? Was ist die Retry-Strategie? Wie werden Poison Messages behandelt?

Diese Fehlerbehandlungsmuster sind kritisch für das Verhalten des Systems, werden aber selten dokumentiert. Sie sind Teil der Architektur und sollten in der Dokumentation sichtbar sein.

Event-Driven-Systeme mit C4 modellieren

Das C4-Modell kann Event-Driven Architectures effektiv darstellen, mit einigen Anpassungen darin, wie jede Ebene verwendet wird.

System Context: Fokus auf Datenflüsse, nicht Aufrufe

Auf System-Context-Ebene sehen Event-Driven und synchrone Architekturen ähnlich aus. Ihr System interagiert mit Benutzern und externen Systemen. Der Hauptunterschied liegt in der Beschriftung der Beziehungen.

Statt "ruft auf" oder "fragt ab" verwenden Sie Labels, die den Datenfluss beschreiben:

  • "Sendet Bestell-Events an"
  • "Empfängt Zahlungsbestätigungen von"
  • "Publiziert Analytics-Events an"

Diese Labels deuten auf die asynchrone Natur der Kommunikation hin, ohne die übergeordnete Sicht mit Implementierungsdetails zu überladen.

Container-Diagramm: Den Broker sichtbar machen

Das Container-Diagramm ist der Punkt, an dem Event-Driven Architecture sich unterscheidet. Der Message Broker (Kafka, RabbitMQ, Amazon SQS/SNS, Google Pub/Sub) sollte ein erstrangiger Container in Ihrem Diagramm sein, kein unsichtbares Implementierungsdetail.

So könnte ein Container-Diagramm für ein Event-Driven E-Commerce-System aussehen:

systems:
  - name: E-Commerce Platform
    type: software_system
    containers:
      - name: Order Service
        type: service
        technologies: [Go, PostgreSQL]
      - name: Inventory Service
        type: service
        technologies: [Java, PostgreSQL]
      - name: Notification Service
        type: service
        technologies: [Python, Redis]
      - name: Analytics Service
        type: service
        technologies: [Python, ClickHouse]
      - name: Event Bus
        type: queue
        technologies: [Apache Kafka]

relationships:
  - from: Order Service
    to: Event Bus
    label: "Publiziert OrderCreated, OrderCancelled"
  - from: Event Bus
    to: Inventory Service
    label: "Liefert Order Events"
  - from: Event Bus
    to: Notification Service
    label: "Liefert Order- und Payment-Events"
  - from: Event Bus
    to: Analytics Service
    label: "Liefert alle Domain Events"
  - from: Inventory Service
    to: Event Bus
    label: "Publiziert InventoryReserved, InventoryReleased"

Beachten Sie, wie der Event Bus im Zentrum des Diagramms steht und die Beziehungen explizit die Event-Typen benennen, die durch ihn fließen. Das macht die Event Flows sichtbar, ohne direkte Pfeile zwischen jedem Producer und jedem Consumer zu erstellen.

Event Channels: Ein erstrangiges Konzept

Einzelne Topics, Queues und Streams innerhalb des Message Brokers verdienen ihre eigene Dokumentation. Jeder Event Channel hat Eigenschaften, die für das Verständnis des Systems wichtig sind:

  • Channel-Name: Der Kafka Topic, die RabbitMQ Queue oder der SQS Queue Name
  • Event-Typen: Welche Events durch diesen Channel fließen
  • Producer: Welche Services an diesen Channel publizieren
  • Consumer: Welche Services von diesem Channel konsumieren
  • Serialisierung: Wie Events codiert werden (JSON, Avro, Protobuf)
  • Partitionierungsstrategie: Wie Events über Partitionen verteilt werden
  • Aufbewahrungsrichtlinie: Wie lange Events gespeichert werden
  • Reihenfolgegarantien: Ob die Reihenfolge bewahrt wird und auf welcher Granularität

In Archyl sind Event Channels ein dedizierter Entitätstyp. Sie erstellen einen Event Channel, spezifizieren seine Eigenschaften und verknüpfen ihn mit den Services, die an ihn produzieren und von ihm konsumieren. Das erzeugt ein strukturiertes, abfragbares Modell Ihrer Event Flows.

Zum Beispiel könnte ein "orders" Event Channel so dokumentiert sein:

  • Name: orders
  • Broker: Kafka
  • Producer: Order Service
  • Consumer: Inventory Service, Notification Service, Analytics Service, Billing Service
  • Event-Typen: OrderCreated, OrderUpdated, OrderCancelled, OrderCompleted
  • Serialisierung: Avro mit Schema Registry
  • Partitionierung: Nach Order ID
  • Aufbewahrung: 7 Tage

Dieses Detailniveau macht die unsichtbare Infrastruktur sichtbar und abfragbar. Wenn ein Entwickler wissen muss, wer Order Events konsumiert, ist die Antwort dokumentiert und auffindbar.

Component-Diagramm: Event Handler und Publisher

Auf Component-Ebene haben Event-Driven Services charakteristische interne Strukturen, die für komplexe Services dokumentiert werden sollten:

  • Event Handler: Komponenten, die bestimmte Event-Typen konsumieren und verarbeiten
  • Event Publisher: Komponenten, die Events produzieren
  • Sagas / Process Manager: Komponenten, die mehrstufige Workflows über Events orchestrieren
  • Projections: Komponenten, die Read Models aus Event Streams aufbauen

Ein Component-Diagramm für den Order Service könnte umfassen:

  • Order Controller -- behandelt HTTP-Requests für die Bestellverwaltung
  • Order Processor -- Kern-Geschäftslogik für Bestellerstellung und -validierung
  • Event Publisher -- publiziert OrderCreated, OrderUpdated, OrderCancelled an Kafka
  • Payment Event Handler -- konsumiert PaymentProcessed und PaymentFailed Events
  • Order Saga -- verwaltet den Bestellabwicklungs-Workflow über Services hinweg

Dokumentieren Sie diese Komponenten, wenn der Service komplex genug ist, um es zu rechtfertigen -- insbesondere für Services, die an Choreographie- oder Orchestrierungsmustern teilnehmen.

Häufige Event-Driven-Patterns dokumentieren

Bestimmte Patterns tauchen in Event-Driven-Systemen wiederholt auf. Sie explizit zu dokumentieren erspart Teams das Reverse Engineering der Patterns aus dem Code.

Event Sourcing

In Event-Sourced-Systemen wird der Zustand einer Entität aus einer Sequenz von Events abgeleitet, anstatt als Snapshot gespeichert zu werden. Der Event Stream ist die Source of Truth, und der aktuelle Zustand ist eine Projection.

Dokumentieren Sie Event Sourcing durch:

  • Identifizierung, welche Entitäten Event-Sourced sind
  • Auflistung der Event-Typen in jedem Event Stream der Entität
  • Dokumentation der Projections, die Read Models aus den Streams ableiten
  • Notierung der Snapshotting-Strategie (falls vorhanden)

CQRS (Command Query Responsibility Segregation)

CQRS trennt Schreiboperationen (Commands) von Leseoperationen (Queries), oft unter Verwendung von Events, um das Read Model mit dem Write Model synchron zu halten.

Dokumentieren Sie CQRS durch:

  • Klare Trennung von Command-Side-Containern und Query-Side-Containern im C4-Modell
  • Dokumentation des Event Flows von der Schreib- zur Leseseite
  • Notierung des Konsistenzmodells (wie weit das Read Model hinterherhängen kann)

Choreographie vs. Orchestrierung

Bei Choreographie reagieren Services unabhängig auf Events. Es gibt keinen zentralen Koordinator. Bei Orchestrierung koordiniert ein zentraler Service (der Orchestrator oder die Saga) den Workflow durch das Senden von Commands und das Lauschen auf Antworten.

Dokumentieren Sie, welches Pattern Ihr System für jeden Workflow verwendet. Bei Choreographie dokumentieren Sie die erwartete Sequenz von Events und die teilnehmenden Services. Bei Orchestrierung dokumentieren Sie den State Machine der Saga und die Commands, die sie ausgibt.

Dead Letter Queues und Retry-Patterns

Dokumentieren Sie Ihre Fehlerbehandlungsstrategie für die Event-Verarbeitung:

  • Welche Events haben Dead Letter Queues?
  • Was ist die Retry-Policy (Anzahl, Backoff-Strategie)?
  • Wer ist verantwortlich für das Monitoring und Reprocessing von DLQ-Events?
  • Welches Alerting ist für DLQ-Akkumulation vorhanden?

In Archyl können Sie DLQs als zusätzliche Event Channels modellieren, die mit den primären Channels verknüpft sind. Das macht die Fehlerbehandlungsinfrastruktur in der Architekturdokumentation sichtbar.

Event Schemas dokumentieren

Event Schemas sind Verträge zwischen Producern und Consumern. Sie verdienen dasselbe Dokumentationsniveau wie API Contracts in synchronen Systemen.

Schema-Dokumentation

Für jeden Event-Typ dokumentieren Sie:

  • Event-Name: Ein klarer, domänenspezifischer Name (OrderCreated, nicht GenericEvent)
  • Schema-Version: Die aktuelle Version des Schemas
  • Felder: Alle Felder mit ihren Typen, Beschreibungen und ob sie erforderlich oder optional sind
  • Beispiel-Payload: Ein repräsentatives JSON/Avro/Protobuf-Beispiel
  • Kompatibilität: Ob das Schema vorwärtskompatibel, rückwärtskompatibel oder vollständig kompatibel ist

Archyls API-Contract-Feature kann verwendet werden, um Event Schemas neben REST- und gRPC-Spezifikationen zu dokumentieren. Verknüpfen Sie den Contract mit dem Event Channel, um eine direkte Verbindung zwischen Schema und Infrastruktur herzustellen.

Schema-Evolutionsstrategie

Dokumentieren Sie den Ansatz Ihres Teams zur Schema-Evolution:

  • Verwenden Sie eine Schema Registry (Confluent Schema Registry, AWS Glue)?
  • Welcher Kompatibilitätsmodus wird durchgesetzt (Backward, Forward, Full)?
  • Wie werden Breaking Changes an Consumer kommuniziert?
  • Was ist der Deprecation-Prozess für alte Schema-Versionen?

Diese Informationen gehören in einen ADR, der mit Ihrer Event-Infrastruktur verknüpft ist. Es ist eine Entscheidung, die das gesamte System betrifft und einmal, klar dokumentiert und von allen Teams referenziert werden sollte.

Event Flows visualisieren

Statische Diagramme können Event-Infrastruktur zeigen, aber sie kämpfen damit, Event Flows zu zeigen -- die Sequenz von Events, die einen Geschäftsprozess implementieren.

Flows für Geschäftsprozesse verwenden

Archyls Flow-Feature ermöglicht es Ihnen, die Sequenz von Events zu dokumentieren, die einen Geschäftsprozess implementieren. Zum Beispiel könnte ein "Bestellung aufgeben"-Flow zeigen:

  1. Kunde gibt Bestellung über Web App auf
  2. API Gateway leitet Request an Order Service weiter
  3. Order Service validiert und persistiert die Bestellung
  4. Order Service publiziert OrderCreated Event an Kafka
  5. Inventory Service konsumiert OrderCreated, reserviert Bestand
  6. Inventory Service publiziert InventoryReserved Event
  7. Payment Service konsumiert InventoryReserved, verarbeitet Zahlung
  8. Payment Service publiziert PaymentProcessed Event
  9. Notification Service konsumiert PaymentProcessed, sendet Bestätigungs-E-Mail

Dieser Flow zeigt das End-to-End-Verhalten, das aus der Event-Driven Architecture hervorgeht. Kein Code eines einzelnen Services enthüllt diesen Flow -- er existiert nur auf Architekturebene.

Overlays für verschiedene Sichten verwenden

Erstellen Sie Overlays, um verschiedene Aspekte Ihrer Event-Driven Architecture zu zeigen:

  • Event-Flow-Overlay: Hebt nur die Event-bezogenen Beziehungen hervor und blendet synchrone Kommunikation aus
  • Producer/Consumer-Overlay: Farbcodiert Services danach, ob sie produzieren, konsumieren oder beides
  • Fehlerbehandlungs-Overlay: Zeigt DLQs, Retry-Pfade und Monitoring

Overlays ermöglichen fokussierte Sichten aus einem einzelnen Architekturmodell und vermeiden die Notwendigkeit mehrerer redundanter Diagramme.

Best Practices

Events nach Domain-Aktionen benennen, nicht nach technischen Operationen

Verwenden Sie Namen wie OrderCreated, PaymentFailed, InventoryReserved -- nicht DataUpdated, MessageSent oder RecordInserted. Domänenspezifische Namen machen die Event Flows auf Architekturebene lesbar.

Die "Warum nicht synchron"-Entscheidung dokumentieren

Für jede Event-Driven-Interaktion gab es eine Entscheidung, asynchron statt synchron zu kommunizieren. Dokumentieren Sie diese Entscheidung. Warum publiziert der Order Service ein Event, statt den Inventory Service direkt aufzurufen? Die Antwort (Entkopplung, Resilienz, Skalierbarkeit) sollte in einem ADR festgehalten werden.

Event-Channel-Dokumentation nah am Code halten

Wenn Ihre Event Schemas im Code definiert sind (Protobuf-Dateien, Avro-Schemas, JSON Schema), verknüpfen Sie die Architekturdokumentation mit diesen Dateien. Das schafft eine Verbindung zwischen der abstrakten Dokumentation und der konkreten Implementierung.

Event Flows bei Architektur-Reviews überprüfen

Gehen Sie bei vierteljährlichen Architektur-Reviews Ihre dokumentierten Event Flows durch. Fragen Sie:

  • Gibt es neue Event-Typen, die nicht dokumentiert sind?
  • Gibt es dokumentierte Event-Typen, die nicht mehr verwendet werden?
  • Wurden neue Consumer hinzugefügt, ohne die Dokumentation zu aktualisieren?
  • Sind die dokumentierten Schemas noch akkurat?

Archyls Drift Detection hilft, diese Fragen automatisch zu beantworten, aber periodische menschliche Überprüfung fängt Dinge ab, die automatisierte Checks übersehen.

Fazit

Event-Driven Architecture zu dokumentieren erfordert bewussten Aufwand, um das Unsichtbare sichtbar zu machen. Events sind designbedingt dafür gemacht, Producer von Consumern zu entkoppeln. Das ist eine architektonische Stärke, aber eine Dokumentationsherausforderung.

Das C4-Modell bietet das Framework: System Context für das große Ganze, Container-Diagramme mit dem Message Broker als erstrangigem Element, Event Channels für detaillierte Topic- und Queue-Dokumentation, und Component-Diagramme für komplexe Event Handler und Sagas.

Archyl bietet das Tooling: Event Channels als erstrangige Entitäten, Flows für die Dokumentation Event-Driven-Geschäftsprozesse, API Contracts für Event Schemas, Overlays für fokussierte Sichten und Drift Detection, um undokumentierte Änderungen zu erkennen.

Dokumentieren Sie Ihre Event-Driven Architecture so, wie Sie sie entwerfen: mit Absicht, Struktur und dem Verständnis, dass das Verhalten des Systems aus den Interaktionen zwischen Services hervorgeht, nicht aus einem einzelnen Service allein.

Starten Sie mit Archyl und machen Sie Ihre Event-Driven Architecture sichtbar, dokumentiert und verstanden.