Domain-Driven Design in der Praxis: Warum unsere Aggregate in MongoDB liegen
von Christoph Knauft · 17.3.2026 · 3 Min. Lesezeit
- Softwarearchitektur
- Softwareentwicklung
Domain-Driven Design (DDD) ist bei uns keine Folienüberschrift, sondern seit Jahren die Grundlage, auf der unsere Produkte entstehen: Wir modellieren Software entlang der Fachdomäne — die Strukturen im Code folgen den Begriffen und Regeln des Geschäfts, nicht den Tabellen einer Datenbank. In diesem Artikel geht es um eine Konsequenz daraus, die sich im Alltag besonders bewährt hat: unsere Aggregate liegen als ganze Dokumente in MongoDB.
Kurz erklärt: das Aggregat
Wer mit DDD arbeitet, schneidet die Domäne in Aggregate: Gruppen von Objekten, die fachlich zusammengehören und gemeinsam konsistent sein müssen. Ein Aggregat hat eine Wurzel (die Aggregate Root), über die jeder Zugriff läuft, und es bildet eine Konsistenzgrenze: Die fachlichen Invarianten — „eine Buchung hat mindestens eine Position”, „die Summe der Positionen ergibt den Buchungsbetrag” — gelten innerhalb des Aggregats und werden dort durchgesetzt. Daraus folgt die wichtigste Faustregel: eine Transaktion ändert genau ein Aggregat.
Das Aggregat ist also die natürliche Einheit, in der unsere Anwendungen denken: Sie laden ein Aggregat, rufen eine fachliche Operation darauf auf und speichern es zurück.
Das Problem mit dem Zerlegen
Genau an dieser Stelle beginnt mit einer relationalen Datenbank die Reibung. Ein Aggregat — sagen wir eine Buchung mit Positionen, Beträgen und Statushistorie — muss beim Speichern in mehrere Tabellen zerlegt und beim Laden wieder zusammengejoint werden. Dazwischen sitzt eine Mapping-Schicht, die ihre eigenen Probleme mitbringt: Lazy-Loading-Fallen, kaskadierende Speicher-Regeln, Migrationsaufwand bei jeder Strukturänderung. Das Objektmodell und das Speichermodell streiten sich — und der ORM moderiert mit wechselndem Erfolg.
Das Auffällige daran: Die Datenbank zerlegt etwas, das fachlich gar nicht zerlegt werden will. Niemand lädt „nur drei Positionen” einer Buchung, um eine Invariante zu prüfen — geprüft wird immer das Ganze.
Aggregat = Dokument
Eine Dokumentendatenbank löst diese Reibung auf die einfachste denkbare Weise: Das Aggregat wird als ein Dokument gespeichert — und als Ganzes geladen.
{
"_id": "buchung-2024-018342",
"status": "BESTAETIGT",
"kunde": { "id": "kunde-5521", "name": "…" },
"positionen": [
{ "bezeichnung": "…", "betrag": { "wert": 1200, "waehrung": "EUR" } },
{ "bezeichnung": "…", "betrag": { "wert": 350, "waehrung": "EUR" } }
],
"historie": [
{ "zeitpunkt": "2024-03-04T09:12:00Z", "ereignis": "ANGELEGT" },
{ "zeitpunkt": "2024-03-04T09:15:21Z", "ereignis": "BESTAETIGT" }
]
}
Die Passung ist kein Zufall, sondern strukturell:
- Die Dokumentgrenze ist die Aggregatgrenze. Was fachlich zusammengehört, liegt physisch zusammen. Das Repository wird trivial: ein
findnach ID, einreplacebeim Speichern — keine Joins, kein Kaskaden-Mapping. - Atomarität passt zur Transaktionsregel. Schreiboperationen auf ein einzelnes Dokument sind atomar. Die DDD-Faustregel „eine Transaktion, ein Aggregat” wird damit nicht nur eingehalten, sondern von der Datenbank gleich mitgeliefert.
- Das Modell darf sich entwickeln. Bekommt das Aggregat ein neues Feld oder eine neue Teilstruktur, ändert sich das Dokument mit — ohne Migrationskaskade über fünf Tabellen. Versionierung und behutsame Migration braucht es trotzdem, aber sie folgt dem Modell statt ihm im Weg zu stehen.
Zwei Regeln halten das Modell dabei sauber. Erstens: Zwischen Aggregaten wird nur per ID referenziert — die Buchung kennt die Kundennummer, nicht das Kundenobjekt. Wer Dokumente ineinander schachtelt, was fachlich getrennte Aggregate sind, holt sich die Konsistenzprobleme zurück, die das Aggregat gerade vermeiden sollte. Zweitens: Lesemodelle sind eigene Modelle. Übersichten und Auswertungen über viele Aggregate hinweg bedienen wir aus eigens dafür gebauten Projektionen statt aus den Aggregat-Dokumenten selbst.
Und wann nicht?
Die ehrliche Ergänzung: MongoDB ist bei uns die Heimat der Aggregate — nicht die Antwort auf alles. Wo Daten ihrer Natur nach tabellarisch sind, wo Ad-hoc-Auswertungen über viele Entitäten dominieren oder ein Bestandssystem relational integriert werden will, setzen wir weiterhin auf MariaDB und MySQL — seit Jahren bewährt und genauso Teil unseres Stacks. Es ist dieselbe Werkzeug-Logik wie überall in unserer Architektur: Die Fachlichkeit entscheidet über das Modell, und das Modell entscheidet über den Speicher — nicht umgekehrt.
Fazit
DDD gibt uns mit dem Aggregat eine klare Einheit für Konsistenz und Transaktionen. Eine Dokumentendatenbank macht diese Einheit auch zur Speichereinheit — und lässt damit eine ganze Schicht an Mapping-Komplexität verschwinden. Wer seine Domäne ernsthaft modelliert, sollte dem Speicher erlauben, diesem Modell zu folgen. Bei uns heißt das seit Jahren: Aggregate als Dokumente, Referenzen per ID, Auswertungen aus Projektionen — und für alles ehrlich Tabellarische weiterhin eine relationale Datenbank.