Playbook

Von CRUD (Create, Read, Update, Delete) zu CQRS (Command Query Responsibility Segregation): Das Problem ist nicht der Code, sondern das Modell (Von Crud Zu CQRS Warum Trennung Noetig Wird)

Was ist CQRS, worin liegt der Unterschied zu CRUD und wann sollte CQRS eingesetzt werden? Ein Leitfaden dazu, warum ein Modell in großen Systemen nicht mehr…

The transition from a shared CRUD model to specialized CQRS models

Warum CRUD jahrelang hervorragend funktioniert

CRUD ist nicht schlecht. Wenn Ihr Team aus drei Personen besteht, ein Produkt entwickelt und täglich einige hundert Anfragen bedient, ist der Ablauf Controller → Service → Repository → Database eine ausgezeichnete Lösung. Er ist schnell, verständlich und für neue Entwickler leicht im Kopf zu behalten.

Am ersten Tag

Product
  ↓
Controller
  ↓
Service
  ↓
Repository
  ↓
Database

Der Bruch kommt nicht von schlechtem Code, sondern vom Produktwachstum. Anfangs listen Sie Produkte. Sechs Monate später möchte Marketing Filter, Sales Sortierung, Operations Export und das Management Analytics sowie Dashboards. Dasselbe Product-Modell bedient plötzlich zwanzig verschiedene Zwecke.

Marketing  → Filter
Sales      → Sortierung
Operations → Export
Management → Analytics + Dashboards

                    ↓

              dasselbe Product-Modell

CRUD ist nicht kaputt gegangen. Die Verantwortung des Modells hat sich verändert.

Das alltägliche Signal ist oft ein harmloser Endpoint:

Heute
GET /products → 10 ms

Sechs Monate später
GET /products
  ↓ Category
  ↓ Reviews
  ↓ Seller
  ↓ Campaign
  ↓ Discount
  ↓ Stock
  ↓ Warehouse
  ↓ Shipment
  ↓ Favorites

derselbe Endpoint wächst, um unterschiedliche Screens zu bedienen

Ein kurzes Glossar für Junior-Entwickler:

📦 Aggregate
Ein Domain-Objekt, das zusammengehörige Fachregeln bewahrt.

📦 Invariant
Eine Fachregel, die in jedem Zustand wahr bleiben muss.

📦 Transaction Boundary
Die Grenze von Änderungen, die gemeinsam oder gar nicht gespeichert werden müssen.

📦 Projection
Ein Prozess, der ein Event in eine neue Leseansicht überführt.

📦 Read Model / DTO
Eine Datenansicht, die nur das enthält, was ein Screen zum Lesen braucht.

Hier beginnt die Geschichte dieses Artikels: CQRS reduziert diese Spannung nicht durch einen Technologiewechsel, sondern indem es unterschiedlichen Absichten unterschiedliche Modelle gibt.

Wann CRUD zum Engpass wird

In CRUD treffen Lesen und Schreiben auf derselben Repräsentation zusammen. Die Write Side möchte Regeln, Konsistenz und kontrollierte Zustandsübergänge. Die Read Side möchte schnelle Filter, kleine DTOs, Suche, Sortierung und für einen Screen geeignete Felder. Wenn ein Modell beides tragen muss, entstehen zwei Kostenarten.

Die erste ist technisch. Ein einfacher Listenscreen lädt Aggregate-Beziehungen, erzeugt vermeidbare Joins und erhöht die Kosten des Datenzugriffs. Die zweite ist kognitiv. Das Hinzufügen eines Reporting-Felds beginnt, die Transaction-Regel eines anderen Teams zu beeinflussen.

100 Nutzer
  → eine API + ein Modell
  → CRUD reicht aus

5.000 Nutzer
  → Listen, Filter, Berichte, Workflows
  → die Absichten des Modells geraten in Konflikt

100.000 Nutzer
  → Lese- und Schreiblast sind asymmetrisch
  → ein Modell erhöht die Kosten der Veränderung

Diese Zahlen sind keine Schwelle. Das eigentliche Signal ist, dass das Modell seine Verantwortung nicht mehr klar ausdrückt.

CQS: die kleine, aber entscheidende Wurzel von CQRS

Bertrand Meyers Prinzip Command Query Separation ist einfach: Eine Frage zu stellen darf die Antwort nicht verändern.

  • Ein Command verändert Zustand. Er trägt Intention und muss keinen Wert zurückgeben.
  • Eine Query liefert Information. Sie verändert keinen beobachtbaren Zustand.

Auf Methodenebene macht das API-Design vorhersehbar. ApproveInvoice ist ein Command; GetInvoiceSummary ist eine Query. UpdateInvoiceStatus ist vielleicht technisch möglich, verbirgt aber die fachliche Intention.

CQRS hebt dieselbe Disziplin auf die Architektur. Das Command Model schützt Fachregeln und Invarianten. Das Query Model produziert die Ansicht, die Nutzer oder System brauchen. Beide können eine Tabelle teilen; zwei Datenbanken, Kafka und Event Sourcing sind keine Voraussetzung.

Wo ein Modell mit sich selbst kollidiert

Betrachten wir ein Reservierungssystem. Die Write Side muss Kapazität, Stornierung, Zahlung und Zeitfensterregeln schützen. Sie braucht starke Grenzen und eine Transaktion. Ein Management-Screen möchte die heutige Auslastung, Zusammenfassungen je Standort und kommende Reservierungen schnell sehen.

Beide Absichten mit einem Entity-Graphen zu bedienen, endet oft so:

GET /reservations
  → Reservation aggregate + Customer + Payment + Availability
  → Query mit Domain-Regeln verflochten
  → langsamer, fragiler Listenscreen

CQRS gibt beiden Absichten eigene Optimierungsziele:

Command: ReserveRoom
  → Kapazität validieren
  → Regeln anwenden
  → in einer Transaktion speichern

Query: GetDailyOccupancy
  → nur Datum, Standort und Zähler lesen
  → ein screen-gerechtes DTO zurückgeben

Das Write Model kann sich nun für Korrektheit und das Read Model für Entdeckung und Geschwindigkeit entwickeln. Das macht nicht jede Query zu O(1), begrenzt die Arbeit aber meist durch Zeilen und Felder der Zielansicht statt durch den gesamten Domain-Graphen.

Entscheidungssignale für CQRS

CQRS wird nicht gewählt, weil es modern klingt. Es wird nützlich, wenn mehrere dieser Signale im selben Bounded Context auftreten:

  1. Aufgabenbasierte UI: Nutzer genehmigen, reservieren, versenden oder erstatten; sie erstellen und bearbeiten nicht nur Zeilen. Command-Namen sollen die Fachsprache tragen.
  2. Asymmetrische Last: Lesetraffic ist deutlich höher als Schreibtraffic, und die Query-Form unterscheidet sich vom Domain-Modell.
  3. Dichte Fachregeln: Ein Aggregate schützt mehrere Invarianten; ein generisches Update beschreibt die Entscheidung nicht mehr.
  4. Unabhängiger Änderungsrhythmus: UI- und Reporting-Bedürfnisse ändern sich schneller als Regeln der Write Side.
  5. Klarer Bounded Context: Der Bereich hat Sprache, Ownership und Erfolgsmaß klar definiert.

Das sind Belege für eine Entscheidung, keine Checkboxen. Das stärkste Signal ist oft, dass Teams auf derselben Entity ständig zwischen Verhalten und Darstellung verhandeln.

Was CQRS nicht ist

Fünf falsche Gleichsetzungen machen CQRS unnötig teuer:

  • Es ist kein Rewrite des gesamten Systems. Beginne im komplexen Bounded Context.
  • Es sind nicht zwei physische Datenbanken. Logische Trennung im Code kann zuerst kommen.
  • Es ist nicht Event Sourcing. Beides kann zusammenarbeiten, aber keines setzt das andere voraus.
  • Es braucht keinen Message Broker. In-Process-Handler können zu Beginn reichen.
  • Es macht nicht jeden Screen zu einem Microservice.

Für einfache Admin-Panels, flache Regeln und geringe Änderungsdynamik ist klassisches CRUD häufig die bessere Wahl: weniger Teile, weniger Betrieb, leichteres Onboarding. Architektonische Reife zeigt sich darin, zu wissen, wann CQRS nicht ergänzt werden sollte.

Der Trade-off

Gewinn Kosten
Commands, die fachliche Intention tragen Mehr Modelle und Contracts
Schnelle Queries für einen Use Case Wiederholte Daten müssen verwaltet werden
Unabhängige Entwicklung von Reads und Writes Zusätzliche Flows müssen beobachtet werden
Skalierungsoption bei asymmetrischer Last Eventual Consistency bei physischer Trennung

CQRS ist deshalb eine Kostenfunktion, keine Framework-Wahl. Die strukturelle Komplexität, die es hinzufügt, muss kleiner bleiben als die Domain- und Betriebs-Komplexität, die es entfernt.

Ein sicherer Einstieg

Beginne mit logischer, nicht mit physischer Trennung. Benenne Commands und Queries in der Fachsprache. Forme Queries zu screen-spezifischen DTOs. Mache Validierung, Berechtigung und Invariant-Grenzen auf der Command Side explizit. Miss. Verschiebe ein Read Model erst dann in einen separaten Store, wenn ein echter Leseengpass oder unabhängiger Skalierungsbedarf nachgewiesen ist.

So entsteht ein lernendes System statt eines irreversiblen Architektur-Sprungs.

Im nächsten Kapitel öffnen wir diese Trennung von innen: Wie arbeiten Command- und Query-Pipelines, Mediator Behaviors, Transaktionsgrenzen und die Outbox-Entscheidung zusammen?

Häufig verwechselte Konzepte

❌ CQRS = Event Sourcing
❌ CQRS = Microservices
❌ CQRS = Kafka
❌ CQRS = Event-driven Architecture

✓ Das sind unabhängige Ansätze.
✓ Sie können zusammenarbeiten; keiner ist Voraussetzung für den anderen.

Betrachte CQRS zuerst als Trennung von Verantwortlichkeiten. Eine separate Datenbank, einen Broker oder Event Stream ergänzt man erst, wenn damit ein gemessener Bedarf beantwortet wird.

Entscheidungsmatrix

Dimension CRUD CQRS
Einfachheit zu Beginn Hoch Mittel
Wartbarkeit bei einfacher Domain Hoch Mittel
Asymmetrische Leseskalierung Begrenzt Stark
Dichte Fachregeln Wird mit der Zeit schwieriger Klarere Grenzen
Betriebskosten Niedrig Mittel bei logischer, hoch bei physischer Trennung

Das ist keine Punktekarte, sondern ein Werkzeug, um Kontext sichtbar zu machen. CRUD-Einfachheit ist in einer einfachen Domain ein echter Vorteil.

CRUD ist nicht das Problem kleiner Systeme. Das Problem ist ein Modell, das gleichzeitig unterschiedliche Absichten darstellen soll. CQRS löst das nicht durch einen Technologiewechsel, sondern durch die Trennung von Verantwortlichkeiten.

FAQ

Häufige Fragen

Worum geht es in „Von CRUD (Create, Read, Update, Delete) zu CQRS (Command Query Responsibility Segregation): Das Problem ist nicht der Code, sondern das Modell“?

Was ist CQRS, worin liegt der Unterschied zu CRUD und wann sollte CQRS eingesetzt werden? Ein Leitfaden dazu, warum ein Modell in großen Systemen nicht mehr…

Was ist die zentrale Aussage?

CQRS Write → Command → Handler → Repository → Database Read → Query → Handler → Read Model / DTO ```

Für wen ist dieser Artikel?

Für Ingenieure und technische Führungskräfte, die Architektur-, Liefer- und Produktionsentscheidungen umsetzen.

Gelernte Engineering-Prinzipien

  • CQRS lehnt CRUD nicht ab; es erkennt, wann ein Modell zwei unterschiedliche Bedürfnisse nicht mehr tragen kann.
  • Architektonische Trennung gehört in den Bounded Context, in dem Komplexität konzentriert ist, nicht in das ganze System.
  • Ein Modell ist nur wertvoll, wenn seine strukturellen Kosten kleiner sind als die Domain-Komplexität, die es entfernt.

Weiterlesen

Weiterlesen

Verwandte Beitrage

Verwandte Beitrage

Verwandte Beitrage

Paylaş