Begriff
CQRS (Command Query Responsibility Segregation)
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
In den meisten Apps sind Lesen und Schreiben gleich.
Datenmodell: "User".
Lesen: SELECT * FROM User.
Schreiben: INSERT INTO User.
Aber in großen Systemen (Amazon, Facebook) wird 1000x mehr gelesen als geschrieben.
Und das Lesen braucht oft ganz andere Formate (z. B. "User + letzte 5 Bestellungen + Adresse").
CQRS sagt:
Trenne das Schreiben (Command) vom Lesen (Query).
Nutze zwei verschiedene Modelle. Vielleicht sogar zwei verschiedene Datenbanken.
Schreib-Modell: Relational (MySQL), strikt, für Konsistenz.
Lese-Modell: NoSQL (Mongo/Redis), denormalisiert, superschnell vorbrechnet.
Merksatz: Ein Architektur-Muster, das die Verantwortung für das Ändern von Daten (Commands) strikt von der Verantwortung für das Abfragen von Daten (Queries) trennt.
Command: "Buche Hotelzimmer". (Komplizierte Logik, prüft Verfügbarkeit, sperrt Zimmer). -> Speichert Event "Zimmer gebucht". Query: "Zeige freie Zimmer". (Liest einfach eine simple Liste aus dem Cache). Die Query-Seite muss gar nicht wissen, wie die Buchungslogik funktioniert. Sie zeigt nur Daten an.
1. Asynchrone Synchronisation
Wie kommen die Daten vom Schreib-Modell ins Lese-Modell? Meistens über Events (Event Bus). Schreib-DB -> Event "UserCreated" -> Worker -> Update Lese-DB. Das führt zu Eventual Consistency.
2. Komplexitäts-Preis
CQRS verdoppelt den Code (zwei Modelle statt einem). Lohnt sich nur, wenn man wirklich Skalierungsprobleme oder extrem komplexe Business-Logik hat. Für einen einfachen Blog ist es Over-Engineering.
1. Event Sourcing als CQRS Backbone
CQRS wird enorm oft mit Event Sourcing gekoppelt. Das Command-System nutzt als Quelle der Wahrheit keine klassische Tabelle (die stets ihren Status überschreibt), sondern ein append-only Event Store.
Jeder Klick (OrderCreated, AddressUpdated) landet unveränderlich als Event in einer Kafka-Queue oder in EventStoreDB. Ein Projection-Worker liest diese Events als Live-Stream konsumierend mit und baut ("projiziert") die read-optimierten Views auf in eine MongoDB. Geht das NoSQL Lese-Modell durch ein fehlerhaftes Release völlig kaputt, wirft man die gesamte Lese-DB eiskalt weg und spielt das Event-Sourcing Log vom Jahr 2012 bis heute in 2 Stunden im Hyper-Speed neu durch, um die Read-Tabellen makellos wiederherzustellen.
2. Task-based UIs
Um echtes Command-Model-Potenzial auszureizen, weicht man von klassischen CRUD-Frontends (die oft anemic Domains sind) massiv ab. Statt einem Formular mit Update-Save-Button, baut man im Frontend Task-based UIs.
Das bedeutet: Wenn ein Benutzer umzieht, aktualisiert er nicht plump user.address, sondern drückt "Adresse Verlegen". Das Frontend feuert ein Command RelocateCustomerCommand. Diese harte intentionelle Sprache (Business Capability) fängt die exakte Fachsprache ab. Das Backend empfängt ein Command mit klarem Intent, wodurch es extrem komplexe Audit-Logiken, Rabattierungsberechnungen und Asynchron-Verteilungen bedienen kann, die in CRUD-Käseschichtarchitekturen gnadenlos zersplittern.
3. Stale Data und CAP Kompromisse
Wenn der Read-Store in CQRS asynchron befüllt wird, leidet das System an Eventual Consistency.
Das bedeutet: Der User transferiert 1000 Euro in der Bank, drückt F5 und sieht das Geld immer noch nicht auf der Query-Seite, da der Event-Replikator 400 Millisekunden laggt. Das ist ein gigantisches UX-Problem.
Engineering-Teams kompensieren dies oft im UI. Nach dem Absetzen eines Commands injiziert die SPA sofort (aus dem Cache) künstlich den projizierten Lese-Status ans UI (Optimistic UI Updates), noch bevor der Backend-Sync bestätigt, oder das Backend blockt den GET Request so lange via WebSockets künstlich auf Eis ("Polling"), bis das Bestätigungs-Event intern durch alle RabbitMQ Queues durchgereicht wurde.
Quick-Check
Muss man zwei Datenbanken haben?
Nein. Man kann CQRS auch mit einer DB machen (Views für Queries, Tables für Commands). Aber der echte Boost kommt oft erst mit getrennten Stores (Polyglot Persistence).Was ist CQS?
Der kleine Bruder (Command Query Separation). Ein Prinzip auf Methoden-Ebene: "Eine Funktion sollte entweder etwas tun (Command) ODER etwas zurückgeben (Query), niemals beides." (Bertrand Meyer). CQRS wendet das auf die ganze Architektur an.Vorteil Security?
Ja. Du kannst das Schreib-Modell extrem sichern (nur Admins), während das Lese-Modell öffentlich im Internet steht (Scale-Out).