Zurück zum Blog
Architektur
Experten-LevelFürSoftware ArchitectsBackend EngineersPlatform Engineers
11 min

Domain-Driven Design 2026: Ein praktischer Leitfaden

Domain-Driven Design ist keine Ordnerstruktur und kein Muster-Katalog. Es ist ein Weg, Software an der Fachlichkeit auszurichten. Ein praktischer Leitfaden für 2026: strategisches vs. taktisches DDD, Bounded Contexts, Aggregate, wann es sich lohnt und wie man startet — ohne Jargon.

domain-driven-designdddbounded-contextubiquitous-languageaggregatesoftwarearchitekturcontext-mapping
Inhalt

Domain-Driven Design hat ein Imageproblem. Die eine Hälfte der Branche hält es für einen akademischen Muster-Katalog — Entities, Repositories, Factories, ein Ordner namens domain/ — und die andere Hälfte für „Microservices, nur mit mehr Meetings“. Beide verfehlen den Kern.

Die ehrliche Version lautet: Bei DDD geht es vor allem darum, Grenzen zu ziehen und sich auf Sprache zu einigen. Die berühmten taktischen Muster sind die kleinere Hälfte. Die wertvolle Hälfte ist strategisch — herauszufinden, was dein Geschäft tatsächlich tut, wo ein Teil endet und ein anderer beginnt, und wo sich echter Modellierungsaufwand lohnt. Dieser Leitfaden geht beide Hälften in einfacher Sprache durch, zeigt, wie sie zusammenhängen — und, genauso wichtig, wann man es sein lassen sollte.

Bounded Contexts mit gemeinsamer Ubiquitous Language: dasselbe Wort bedeutet in Vertrieb, Abrechnung und Support Verschiedenes.

Woher DDD wirklich kommt

Domain-Driven Design wurde von Eric Evans in seinem Buch Domain-Driven Design: Tackling Complexity in the Heart of Software (2003) benannt. Die Kernaussage ist einfach und in vielen Teams bis heute radikal: Das Schwierigste an den meisten Softwareprojekten ist nicht die Technik — es ist die Fachlichkeit. Die verworrenen Geschäftsregeln von Versicherung, Logistik, Gesundheitswesen oder Handel machen ein System wirklich schwer, und der beste Weg, diese Komplexität zu zähmen, ist ein gemeinsames Modell der Domäne, das das Design treibt.

Das ist alles. Alles Übrige in DDD ist Maschinerie im Dienst dieser einen Idee.

Der Kern: Modell und Ubiquitous Language

Zwei Konzepte stehen im Zentrum von DDD, und wenn du nur zwei Dinge mitnimmst, dann diese.

Das Modell ist ein bewusstes, vereinfachtes Abbild der Domäne — die Konzepte, Regeln und Beziehungen, die zählen, und nichts, was nicht zählt. Es ist nicht das Datenbankschema und nicht das Klassendiagramm; es ist das gemeinsame mentale Modell, mit dem das ganze Team denkt.

Die Ubiquitous Language ist das Vokabular dieses Modells — und die Regel lautet: Alle verwenden es überall. Fachexperten, Produktleute, Entwickler, Tests und der Code selbst benutzen dieselben Wörter für dieselben Dinge. Sagt das Geschäft „eine Police ist erloschen“, dann gibt es im Code einen Zustand erloschen, kein status = 3. Wenn die Sprache in Gesprächen der Sprache im Code entspricht, verschwindet eine ganze Kategorie von Übersetzungsfehlern und Missverständnissen einfach.

Das ist die günstigste, wirkungsvollste Praxis in ganz DDD, und sie braucht kein Framework. Du kannst morgen anfangen: höre zu, wie die Fachexperten wirklich reden, schreibe diese Wörter auf und weigere dich, eine parallele Entwickler-Fachsprache zu erfinden.

Strategisches DDD: Die Hälfte, die am meisten zählt

Beim strategischen Design geht es um das große Bild — wie du eine große Domäne in Teile zerlegst, die je für sich Sinn ergeben. Hier verdient DDD sein Geld, und genau diesen Teil überspringen Teams am häufigsten.

Bounded Contexts

Ein Bounded Context ist eine explizite Grenze, innerhalb derer ein Modell und eine Sprache konsistent sind. Die entscheidende Erkenntnis: Dasselbe Wort bedeutet in verschiedenen Teilen des Geschäfts Verschiedenes.

Nimm „Kunde“:

  • Im Vertrieb ist ein Kunde ein Lead mit Pipeline-Phase, Wahrscheinlichkeit und Account-Verantwortlichem.
  • In der Abrechnung ist ein Kunde ein Konto mit Zahlungsbedingungen, Rechnungen und Kreditlimit.
  • Im Support ist ein Kunde eine Person mit Kontakthistorie und offenen Tickets.

Der Instinkt vieler Teams ist, eine einzige riesige Kunde-Klasse zu bauen, die allen drei dient. Dieses Objekt wird zu einem aufgeblähten Chaos, das niemandem gehört und das alle zu ändern fürchten. DDD sagt das Gegenteil: Jeder Kontext bekommt sein eigenes Kundenmodell, auf seine Bedürfnisse zugeschnitten, und man definiert explizit, wie sie zusammenhängen. Jeder Bounded Context ist klein, kohärent und gehört einem Team, das eine Sprache teilt.

Derselbe Begriff, in drei Bounded Contexts unterschiedlich modelliert, jeder mit eigener Ubiquitous Language, verbunden durch explizite Übersetzung.

Subdomänen: Wo du deine besten Leute einsetzt

Nicht jeder Teil deines Systems verdient dieselbe Investition. DDD teilt den Problemraum in drei Arten von Subdomäne:

  • Kern-Domäne (Core) — das, was dein Geschäft wirklich anders und schwer kopierbar macht. Hierhin gehören deine besten Ingenieure, deine tiefste Modellierung und dein voller DDD-Einsatz. Bei einem Logistiker sind das Routing und Disposition; bei einer Bank Risiko und Abwicklung.
  • Unterstützende Subdomäne (Supporting) — nötig für das Geschäft, aber kein Alleinstellungsmerkmal. Sie muss existieren und funktionieren, muss aber nicht brillant sein. Baue sie einfach.
  • Generische Subdomäne (Generic) — gelöste Probleme, die jedes Unternehmen hat: Authentifizierung, Benachrichtigungen, Zahlungen, PDF-Erzeugung. Modelliere diese nicht — kaufe sie ein oder nutze einen fertigen Dienst. Modellierungsenergie hier zu verbrennen ist reine Verschwendung.

Die wertvollste strategische Frage in DDD lautet: Was ist unsere Kern-Domäne? Alles andere folgt daraus, diese Antwort richtig zu treffen.

Context Mapping: Wie die Teile zusammenhängen

Sobald du mehrere Bounded Contexts hast, musst du beschreiben, wie sie verbunden sind — technisch und organisatorisch. Das ist eine Context Map, und DDD gibt ihr ein Vokabular:

  • Partnership — zwei Kontexte (und ihre Teams) gewinnen oder verlieren gemeinsam und stimmen sich eng ab.
  • Customer–Supplier — ein nachgelagerter Kontext hängt von einem vorgelagerten ab, und das vorgelagerte Team berücksichtigt die Bedürfnisse des nachgelagerten in seinen Plänen.
  • Conformist — der nachgelagerte Kontext übernimmt das Modell des vorgelagerten einfach so (üblich, wenn der Upstream ein Anbieter oder ein Team ist, das sich nicht anpasst).
  • Anticorruption Layer (ACL) — der nachgelagerte Kontext baut eine Übersetzungsschicht, die das Modell des Upstream in sein eigenes übersetzt, damit ein unsauberes oder fremdes Modell nicht eindringt und das lokale verdirbt. Eines der nützlichsten Muster in der Praxis, besonders bei der Integration von Altsystemen.
  • Open Host Service / Published Language — ein vorgelagerter Kontext bietet eine wohldefinierte, dokumentierte Schnittstelle (oft eine API mit gemeinsamem Schema), damit viele Nachgelagerte gleich integrieren.

Du musst den Katalog nicht auswendig lernen. Der Punkt ist: Die Beziehungen zwischen Kontexten sind eine Design-Entscheidung, kein Zufall — und sie explizit zu zeichnen bewahrt dich vor dem klassischen „Big Ball of Mud“, in dem alles von allem abhängt.

Eine Context Map: Kern-, unterstützende und generische Subdomänen, verbunden durch Customer-Supplier- und Anticorruption-Layer-Beziehungen.

Taktisches DDD: Die Bausteine

Beim taktischen Design geht es um das Werkzeug, um dein Modell innerhalb eines Bounded Context im Code auszudrücken. Das sind die Muster, an die sich alle erinnern — aber denk daran, sie sind die kleinere Hälfte, und sie zählen erst, wenn du gute Grenzen gezogen hast.

  • Entity — ein Objekt, das durch seine Identität definiert ist, nicht durch seine Attribute. Ein User mit ID 42 ist derselbe User, auch wenn Name und E-Mail sich ändern. Zwei Entities sind gleich, wenn ihre IDs übereinstimmen.
  • Value Object — ein Objekt, das vollständig durch seine Werte definiert ist, ohne Identität und idealerweise unveränderlich. Money(10, "EUR"), ein DateRange, eine Address. Zwei Value Objects sind gleich, wenn ihre Werte gleich sind. Value Objects zu bevorzugen macht Code sicherer und klarer — ein Money-Typ kann nicht versehentlich zu einer Distance addiert werden.
  • Aggregat — eine Gruppe von Entities und Value Objects, die sich gemeinsam ändern und als Einheit konsistent bleiben müssen. Eine Entity ist die Aggregat-Wurzel: das einzige Objekt, das externer Code referenzieren darf, und der Hüter der Invarianten des Aggregats (der Regeln, die immer gelten müssen). Ein Order-Aggregat könnte OrderLine-Value-Objects enthalten und „eine Bestellsumme kann nie negativ sein“ durchsetzen.
  • Domain Event — ein Datensatz, dass in der Domäne etwas Bedeutsames passiert ist: OrderPlaced, PaymentReceived, PolicyLapsed. Events halten Aggregate und Kontexte synchron, ohne enge Kopplung, und passen sauber auf ein event-getriebenes Rückgrat.
  • Repository — eine sammlungsähnliche Abstraktion zum Laden und Speichern von Aggregaten, die die Persistenzdetails verbirgt. Du fragst ein Repository per Identität nach einem Aggregat; du schreibst kein SQL im Domänencode.
  • Domain Service — ein Zuhause für Domänenoperationen, die nicht natürlich zu einer einzelnen Entity oder einem Value Object gehören, etwa eine Überweisung zwischen zwei Konten.

Gute Aggregate entwerfen

Aggregate sind das taktische Muster, das die meisten am ehesten falsch machen — deshalb lohnt sich Genauigkeit. Die weit gelehrten Regeln (geschärft durch Vaughn Vernons Effective Aggregate Design) lauten:

  1. Aggregate klein halten. Ein großes Aggregat bedeutet große Transaktionen und viel Konkurrenz um Sperren. Bevorzuge viele kleine Aggregate gegenüber einem riesigen.
  2. Invarianten über die Wurzel schützen. Alle Änderungen laufen über die Aggregat-Wurzel, damit sie die Regeln durchsetzen kann. Nichts greift hinein und verändert ein Kind direkt.
  3. Andere Aggregate per Identität referenzieren, nicht per Objekt. Ein Order hält eine CustomerId, kein ganzes Customer-Objekt. So bleiben Aggregate unabhängig und einzeln ladbar.
  4. Ein Aggregat pro Transaktion. Eine einzelne Transaktion sollte genau ein Aggregat ändern. Wenn ein anderes Aggregat reagieren muss, veröffentliche ein Domain Event und aktualisiere es in einer separaten Transaktion — und akzeptiere Eventual Consistency.

Diese letzte Regel ist die Brücke zwischen taktischem DDD und verteilten Systemen: Konsistenz innerhalb eines Aggregats ist sofort; Konsistenz zwischen Aggregaten ist eventual, getragen von Events.

Anatomie eines Aggregats: eine Wurzel-Entity, die Invarianten über ihre Value Objects wahrt, ein anderes Aggregat per ID referenziert und ein Domain Event auslöst.

DDD und Microservices

Weil ein Bounded Context ein kohärentes, in sich geschlossenes Modell mit eigener Sprache und eigenen Daten ist, hat er meist genau die richtige Größe für einen Microservice. Das ist die eigentliche Verbindung zwischen DDD und Microservices: DDD gibt dir einen fundierten Weg zu entscheiden, wo Servicegrenzen verlaufen, statt nach technischer Schicht oder nach Bauchgefühl zu trennen.

Aber die beiden sind nicht dasselbe, und sie zu verwechseln richtet echten Schaden an:

  • Du kannst DDD in einem modularen Monolithen betreiben — ein Deployment, ein Modul pro Bounded Context, saubere Grenzen im Code. Für die meisten Teams ist das der pragmatische Startpunkt.
  • Du kannst Microservices ohne DDD bauen — und Teams, die das tun, schneiden Services oft entlang der falschen Linien und landen bei einem verteilten Monolithen: Services, die so gekoppelt sind, dass sie zusammen deployt werden müssen.

Die Reihenfolge zählt: Zuerst die Bounded Contexts entdecken, dann das Deployment entscheiden. Trenne einen Kontext in einen eigenen Service, wenn es einen konkreten Grund gibt — unabhängige Skalierung, Team-Autonomie, Fehlerisolation — nicht weil Microservices gerade in Mode sind.

Wann sich DDD lohnt — und wann nicht

DDD ist eine Investition, und wie jede Investition bringt sie am falschen Ort eine schlechte Rendite.

Greif zu DDD, wenn:

  • Die Kern-Domäne wirklich komplex ist — reiche Geschäftsregeln, die schwer richtig und teuer falsch zu machen sind (Versicherung, Logistik, Handel, Gesundheitswesen, Steuern).
  • Die Domäne sich ständig weiterentwickelt, sodass ein klares Modell und eine klare Sprache sich über Jahre immer wieder auszahlen.
  • Mehrere Teams am selben großen System arbeiten müssen, ohne sich in die Quere zu kommen — Bounded Contexts geben ihnen saubere Nahtstellen.

Lass das Meiste davon, wenn:

  • Die App im Wesentlichen CRUD ist — Formulare über Daten mit wenig echter Logik. Das volle taktische Werkzeug ist hier reine Zeremonie.
  • Du in einer generischen oder unterstützenden Subdomäne arbeitest — kaufen, nicht modellieren.
  • Das Team klein und das Produkt jung ist und die Domäne noch nicht gut genug verstanden ist, um gute Grenzen zu ziehen.

Beachte die Asymmetrie: Selbst in einem einfachen Projekt sind die strategischen Praktiken — Ubiquitous Language, die eigene Kern-Domäne kennen — günstig und fast immer lohnend. Es ist die schwere taktische Maschinerie, die du selektiv einsetzen solltest.

Häufige Fehler

Ein paar Fallen tauchen immer wieder auf:

  • Nur taktisches DDD betreiben. Teams übernehmen Entities, Repositories und einen domain/-Ordner, ziehen aber nie Bounded Contexts und reden nie mit Fachexperten. Das ist DDD-Cosplay — die teuren Muster ohne den Ertrag.
  • Ein Modell für alles. Sich weigern, „Kunde“ in verschiedenen Kontexten Verschiedenes bedeuten zu lassen, und stattdessen ein Gott-Objekt bauen.
  • Anämisches Domänenmodell. Entities, die nur Sammlungen von Gettern und Settern sind, während die gesamte Logik in „Service“-Klassen steckt. Die Regeln gehören in das Modell.
  • Zu große Aggregate. Das halbe Schema in ein Aggregat ziehen und danach ewig mit Transaktionskonkurrenz und Lock-Timeouts kämpfen.
  • Generische Subdomänen modellieren. Liebevoll ein Authentifizierungs- oder Benachrichtigungssystem von Hand bauen, das man hätte einkaufen sollen.

Wie man wirklich anfängt

Man führt DDD nicht ein, indem man ein Buch liest und Ordner umbenennt. Fang klein und strategisch an:

  1. Auf die Sprache hören. Setz dich mit Fachexperten zusammen und schreib die genauen Wörter auf, die sie benutzen. Dieses Vokabular ist der Keim deiner Ubiquitous Language.
  2. Ein Event Storming durchführen. Diese Workshop-Technik (von Alberto Brandolini) bringt Entwickler und Fachexperten an eine Wand voller Klebezettel, um die Events, Kommandos und — entscheidend — die natürlichen Grenzen der Domäne zu kartieren. Der schnellste Weg, Bounded Contexts zu entdecken.
  3. Deine Kern-Domäne benennen. Entscheide, wo sich das Geschäft wirklich differenziert, und einige dich darauf, deinen besten Modellierungsaufwand dorthin zu stecken und den Rest einfach zu halten.
  4. Eine grobe Context Map zeichnen. Schon eine Whiteboard-Skizze deiner Kontexte und ihrer Beziehungen legt verborgene Kopplung und schlechte Abhängigkeiten offen.
  5. Taktische Muster nur im Kern anwenden. Führe Aggregate, Value Objects und Domain Events dort ein, wo die Komplexität sie rechtfertigt — nicht überall.

Das Fazit

Domain-Driven Design ist keine Ordnerstruktur und kein Synonym für Microservices. Es ist eine Disziplin, um komplexe Domänen zu zähmen, indem man sie bewusst modelliert und ehrliche Grenzen zieht. Die strategische Hälfte — Ubiquitous Language, Bounded Contexts, die eigene Kern-Domäne kennen — ist der Teil, der sich fast überall auszahlt und fast nichts kostet. Die taktische Hälfte ist ein scharfes Werkzeug, das in wirklich komplexen Kern-Domänen glänzt und überall sonst nur Zeremonie hinzufügt.

Nutze es, wo die Domäne schwer ist. Halte alles andere einfach. Das ist gut gemachtes DDD — ganz ohne Jargon.

Häufig gestellte Fragen

Was ist Domain-Driven Design einfach erklärt?

Domain-Driven Design (DDD) ist ein Ansatz zum Bau von Software, bei dem das Design von einem tiefen Modell der Fachlichkeit getrieben wird und nicht von technischen Belangen. In der Praxis heißt das: mit Fachexperten sprechen, sich auf ein gemeinsames Vokabular einigen (die Ubiquitous Language) und diese Sprache samt ihren Regeln direkt im Code abbilden. DDD hat zwei Hälften: das strategische Design, bei dem es um Grenzen zwischen Teilen des Geschäfts geht (Bounded Contexts) und darum, wo man investiert; und das taktische Design, eine Sammlung von Bausteinen wie Entities, Value Objects und Aggregaten, um das Modell im Code auszudrücken. Der strategische Teil trägt den meisten Wert.

Was ist ein Bounded Context in DDD?

Ein Bounded Context ist eine explizite Grenze, innerhalb derer ein bestimmtes Domänenmodell und seine Sprache konsistent und eindeutig sind. Die zentrale Einsicht: Dasselbe Wort bedeutet in verschiedenen Teilen eines Geschäfts Verschiedenes. Ein 'Kunde' im Vertriebskontext (ein Lead mit Pipeline-Phase) ist nicht dasselbe wie ein 'Kunde' im Abrechnungskontext (ein Konto mit Zahlungsbedingungen) oder im Support-Kontext (eine Person mit Tickets). Statt ein riesiges gemeinsames Modell zu erzwingen, lässt DDD jeden Kontext sein eigenes Modell haben und definiert explizit, wie die Kontexte zueinander übersetzen. Bounded Contexts sind zugleich der natürlichste Ort, um Microservice- oder Modulgrenzen zu ziehen.

Was ist ein Aggregat in Domain-Driven Design?

Ein Aggregat ist eine Gruppe zusammengehöriger Objekte, die für Datenänderungen als eine Einheit behandelt werden, mit einem Objekt als Aggregat-Wurzel (Aggregate Root). Die Wurzel ist der einzige Einstiegspunkt: Externer Code darf nur eine Referenz auf die Wurzel halten, und alle Änderungen laufen über sie, damit sie die Invarianten des Aggregats durchsetzen kann (die Geschäftsregeln, die immer gelten müssen). Die praktische Leitlinie: Aggregate klein halten, genau ein Aggregat pro Datenbanktransaktion, andere Aggregate per Identität statt per Objektreferenz referenzieren und andere Aggregate asynchron über Domain Events aktualisieren, wenn Eventual Consistency akzeptabel ist. So bleibt das Modell konsistent, ohne riesige, umkämpfte Transaktionen zu erzeugen.

Ist Domain-Driven Design dasselbe wie Microservices?

Nein, aber sie passen gut zusammen. DDD dreht sich ums Modellieren und Grenzenziehen; Microservices sind ein Deployment-Stil. Die Verbindung: Ein Bounded Context hat meist genau die richtige Größe für einen Microservice, deshalb nutzen viele Teams das strategische Design von DDD, um zu entscheiden, wo ein System in Services aufgeteilt wird. Man kann DDD in einem einzigen Monolithen betreiben (ein modularer Monolith mit einem Modul pro Bounded Context ist ein sehr verbreitetes, pragmatisches Setup), und man kann Microservices ohne DDD bauen (oft schlecht, weil die Grenzen an den falschen Stellen landen). Die beste Praxis: Zuerst mit DDD die Bounded Contexts entdecken und erst dann entscheiden, ob jeder ein eigener Service sein soll.

Wann ist DDD übertrieben?

DDD lohnt sich bei einer komplexen, sich verändernden Kern-Domäne mit echten Geschäftsregeln, die schwer richtig hinzubekommen sind — denke an Versicherung, Logistik, Handel oder Gesundheitswesen. Übertrieben ist es bei einfachen CRUD-Anwendungen, dünnen Dateneingabe-Masken und generischen Subdomänen (Authentifizierung, Benachrichtigungen, Zahlungen), die man einkaufen oder als fertigen Dienst nutzen sollte, statt sie tief zu modellieren. Das gesamte taktische Werkzeug — Aggregate, Repositories, Domain Events, Factories — auf eine To-do-Liste anzuwenden, bringt Zeremonie ohne Wert. Die ehrliche Regel: DDD-Aufwand in die Kern-Domäne stecken, wo sich das Geschäft wirklich differenziert, und alles andere bewusst einfach halten.

Aus der Community

Diskussion im Fediverse

Antworten von Mastodon und Bluesky — direkt aus dem offenen Netz, ohne Tracking.

Antworten werden geladen …

ENDE