A team proposes CQRS with event sourcing for a new internal admin tool because the patterns are considered scalable. Evaluate.
Show the full answer Hide the answer
What is being tested
Whether you can separate two patterns that are routinely conflated, and whether you will decline complexity that has no corresponding requirement.
First, separate them
CQRS is separating the write model from the read model. Event sourcing is storing state as a sequence of events rather than as current values. They are independent. You can have CQRS with a plain relational write model and a search index as the read model — and most useful CQRS is exactly that. Teams that adopt them together, believing one requires the other, take on far more difficulty than the problem warranted.
What each actually solves
CQRS solves shape divergence. When the write model and read model want genuinely incompatible structures — a normalised transactional schema against a geospatial, faceted, ranked search index — one schema cannot serve both. That is a real and common problem, and CQRS is the right answer to it.
Event sourcing solves auditability and temporal queries. When the business needs to answer "what was the state on the 14th and who changed it", or when the events themselves are the domain (a ledger, a trading book, a regulated approval chain), storing events is the honest model rather than a reconstruction.
Against an admin tool
An internal admin tool typically has:
- Low read volume, and reads whose shape is similar to the write shape.
- Modest write volume.
- No consumers other than itself.
- A handful of users.
None of the problems either pattern solves. What it would gain instead:
- Eventual consistency for its own users. An admin changes a value and does not see it, which is precisely the interaction that makes an internal tool feel broken.
- Projection code and lag monitoring for a system that could have been a
SELECT. - Versioned events forever. Once events are the source of truth, every schema change must handle every historical version, permanently. This is the cost that people consistently underestimate, and it does not go away.
- A much harder debugging story and a much steeper onboarding curve for a tool that should be boring.
The recommendation
Plain CRUD over a relational database. Add an audit table if history matters — which gives 90% of the value of event sourcing for 5% of the cost.
What would change the answer
- A genuine audit or regulatory requirement for a full, immutable change history with the ability to reconstruct past states — then event sourcing is doing real work.
- Read shapes that diverge sharply from write shapes — a complex search over the admin data, or heavy cross-entity reporting — then CQRS for that one read path, without event sourcing.
- Multiple independent consumers of the changes.
Note that each of those justifies one of the patterns, for one part of the system. That is how they should almost always be adopted.
The general point
"It is scalable" is not a requirement. Every pattern is scalable in the dimension it was designed for and costly in every other. The question is always which specific problem you have, and whether you have it yet.