An architecture review proposes multi-region active-active, event sourcing, CQRS and a service mesh for an internal tool with 500 users. Write the simpler architecture, and state the specific facts that would justify each rejected pattern later.
Show the full answer Hide the answer
The simpler architecture
One deployable application, one managed Postgres with automated backups and point-in-time recovery, one region, a managed load balancer, and the platform's standard observability. Background work in a table-backed queue in the same database. Deploy on a rolling update.
For 500 internal users this is not a compromise — it is the design that best serves the actual quality attributes, which are almost certainly time-to-market, cost, and the ability of a small team to operate it.
Why each proposed pattern is wrong here
- Multi-region active-active buys survival of a regional outage, and costs write-conflict resolution on every entity, cross-region latency inside transactions, and doubled infrastructure. For an internal tool, the correct response to a regional outage is "the tool is down for a few hours," which is exactly what the business would choose if asked.
- Event sourcing buys a perfect audit trail and temporal queries, and costs schema evolution of events, projection rebuild machinery, and a much harder debugging story. The team will implement it, then build a read model that is just the table they would have had.
- CQRS buys independent scaling of reads and writes, and costs eventual consistency in the UI for a workload with no read/write asymmetry.
- A service mesh buys uniform mTLS, retries and telemetry across many services. There is one service.
The facts that would justify each later
| Pattern | The fact that flips the decision |
|---|---|
| Multi-region | A signed availability commitment that a single-region outage would breach, or a residency rule requiring local serving |
| Event sourcing | A regulator or auditor requiring reconstruction of any historical state, written down and testable |
| CQRS | A measured read workload that cannot be served from the write model without harming writes, after indexing and caching are exhausted |
| Service mesh | Enough services that per-service TLS, retry and telemetry configuration has become a real, measured maintenance cost |
How to say it in the review
Not "this is over-engineered" but "which requirement is each of these serving, and what would I observe if it were absent?" If the answer to the second question is "nothing, for several years," the pattern is a bet on a future that has not been shown to exist — and the cost is paid every day until then, by a team that could have been shipping.
The defensible position is reversibility: build the simple version behind boundaries clean enough that each pattern can be introduced when its triggering fact appears.