A colleague proposes introducing CQRS — separate write and read models — for a new internal admin tool that has low traffic and simple CRUD screens. What's your reasoning for pushing back, and what are the concrete signals that would change your mind?
answer
- resume-driven architecture warning
- single model = simpler until proven otherwise
- need a measurable asymmetry, not 'might scale someday'
- cost is ongoing and sticky, hard to unwind
- contrast: admin CRUD vs. high-read catalog
basics
~20 sIf reads and writes are low-volume and shaped similarly, splitting into two models just adds complexity (sync pipeline, staleness, more code) with no real benefit — you'd push back and ask what specific problem it's meant to solve.
solid answer
~40 sCQRS's cost — dual models, an async sync mechanism, eventual consistency, doubled operational surface — is only worth paying when there's a real, specific asymmetry it solves: very different read/write scaling ratios, read query shapes that genuinely can't be served well by the write model's schema, or a need to scale reads independently of writes. A low-traffic admin CRUD tool typically has none of that: one model can serve both simple reads and writes fine, with room to grow via caching or read replicas long before a full model split is justified. Signals that would change the reasoning: the reads start needing a fundamentally different shape (search, complex aggregation) than the write schema naturally provides, or read and write load diverge sharply enough that scaling them together becomes wasteful or a bottleneck.
go deeper
Should sense that adding two models for a small, low-traffic tool feels like overkill, even without being able to name the specific alternatives.
Should name at least one lighter-weight alternative (read replicas, caching) and explain why it's cheaper for this case.
Should articulate the specific measurable signals that would flip the decision, and push back on the proposal with concrete reasoning rather than a vague 'let's keep it simple.'
Should set org-level guidance (e.g. an architecture decision record or default guidance) on when CQRS is justified, to prevent this decision from being re-litigated ad hoc project by project, and weigh the sunk, sticky cost of unwinding it later.
## The most common mistake The single most common CQRS mistake in the field isn't misusing it once adopted — it's adopting it where a single model would have been simpler, cheaper, and just as correct. Pushing back on CQRS for a low-traffic admin CRUD tool is really an application of a general engineering principle: **architectural complexity should be introduced to solve a demonstrated problem**, not spent pre-emptively on the chance it might be needed. CQRS specifically trades simplicity for scalability and flexibility along the read/write axis, and if that axis isn't under strain, the trade is pure cost with no offsetting benefit. ## What one shared model already gives you Concretely, a single shared model handles the common case well: - one schema, one set of classes/entities, one database; - straightforward transactional consistency (a read immediately after a write sees the write — no eventual-consistency window to reason about); - one thing to test, deploy, and operate. For an admin tool with simple CRUD screens and low traffic, this is very likely sufficient for the tool's entire lifetime — the query patterns (list records, filter by a couple of fields, edit one record) are exactly what a normalized relational schema serves well natively, without any denormalization or projection needed. Reaching for CQRS here means paying its costs — building and maintaining a second model, standing up a sync mechanism, teaching the team to reason about staleness, doubling the operational surface described elsewhere in this topic — for zero measurable benefit, since there's no asymmetry or scaling pain for it to fix. This is sometimes called 'CQRS as **resume-driven architecture**': applying an interesting pattern because it's interesting, not because the system needs it. ## The subtler cost There's also a subtler cost worth naming to a colleague: **cognitive load and hiring/onboarding friction**. Every engineer who touches this admin tool now has to understand two models and an async sync boundary, even for a simple bug fix, which slows down exactly the kind of small internal tool that's supposed to be cheap to maintain. And CQRS is not free to unwind either — once a read model has downstream consumers (reports built against it, other services querying it), collapsing back to a single model is its own migration project, so the cost isn't just paid once at adoption but ongoing and sticky. ## The signals that would change the answer The signals that would legitimately justify introducing CQRS — and that a senior engineer should be listening for — are specific and measurable, not vague ('it'll scale better someday'). 1. **First**, a real, demonstrated asymmetry in read/write volume or ratio: if reads start dramatically outpacing writes (say, orders of magnitude) such that read traffic is causing contention or forcing over-provisioning of write-side infrastructure just to serve reads. 2. **Second**, a genuine shape mismatch: the read side needs a fundamentally different query shape than the write schema naturally supports — full-text search, complex multi-entity aggregation/reporting, or a completely different access pattern (e.g. time-series rollups) that would require either expensive JOINs against the write schema or denormalizing the write schema itself (which pollutes it and slows writes). 3. **Third**, a need to scale reads and writes independently — for instance, wanting to run read replicas in multiple regions for latency while keeping writes centralized for consistency, which is easier to reason about with an explicit read/write split. ## The contrasting case A worked example of the right call: the same team also owns a customer-facing product catalog with millions of reads a day (browsing, search, filtering) against a write side that only changes when merchandisers update a few hundred products a day. Here the asymmetry is obvious and severe, the read shape (faceted search, filtering) is a poor natural fit for the write schema, and the two sides have wildly different scaling needs. That's a legitimate CQRS candidate — worth the sync pipeline and eventual consistency, because customers browsing slightly stale search results is an acceptable trade for a system that can actually handle the load. The contrast between the two cases — reject for the admin tool, adopt for the catalog — is the core senior-level judgment call this topic tests: not whether CQRS is 'good' or 'bad' in the abstract, but whether the specific system in front of you has the asymmetry that makes its cost worth paying. A senior engineer should be able to articulate this trade-off explicitly to a colleague rather than either rubber-stamping the proposal or rejecting it on gut feel alone.
- If the admin tool later does grow — say, a reporting feature that needs heavy aggregation — what would you reach for before jumping straight to full CQRS?Cheaper intermediate steps first: a read replica of the same database for isolating heavy read queries from write traffic, or a scheduled materialized view / rollup table refreshed periodically for the reporting queries specifically. Both solve read/write contention or shape mismatch without the full cost of a separately maintained model and event-driven sync pipeline, and can be adopted incrementally for just the pain point rather than the whole system.
- Is it possible to apply CQRS to only part of a system rather than all-or-nothing?Yes — CQRS is commonly applied per-aggregate or per-bounded-context rather than system-wide; a team might keep a simple single model for most entities and introduce a read projection only for the one high-read, shape-mismatched entity (like the product catalog). This bounds the cost to where the benefit actually is, which is usually the right default over an all-or-nothing adoption.
Like installing a commercial dual-zone HVAC system in a one-room studio apartment because a mansion down the street benefits from zoned climate control — the pattern is real and valuable somewhere, just not for a room with one set of needs and one thermostat's worth of load.
saying these in an interview costs you the question
- Advocates CQRS for every new service by default
- Can't articulate what specific problem CQRS solves in this case
- Dismisses the eventual-consistency and operational cost as negligible
- Doesn't consider cheaper alternatives (read replicas, caching, materialized views) before proposing a full model split
- Treats 'it might need to scale eventually' as sufficient justification without evidence