Architecture Tradeoff Explorer
Every comparison answers the same five questions — use when, avoid when, complexity, operational cost, failure modes — so the decision is about your constraints, not the fashion of the year.
Monolith vs MicroservicesREST vs GraphQLREST vs gRPCSynchronous call vs Asynchronous (queue)Relational (SQL) vs NoSQL (document / key-value)Queue (point-to-point) vs Pub/Sub (topic)Event-driven vs Request/responseCache (Redis / CDN / in-process) vs DatabaseCQRS vs CRUDEvent sourcing vs State storage
Store every change as an immutable event and derive the current state by replay, or store the current state and overwrite it. Event sourcing gives a perfect audit log and temporal queries; state storage gives simplicity and a query you can run today.
| Event sourcing Event Sourcing | State storage Database · Transactions and ACID | |
|---|---|---|
| Use when | The history is the product — ledgers, audit-critical domains, workflows where "how did it get here" must be answered exactly — and you can afford projections. | The current state is what matters, the domain is CRUD-shaped, and an audit table or change log covers the compliance need. The default. |
| Avoid when | Events would be EntityUpdated{diff} with no domain meaning, deletion under GDPR is a requirement you cannot meet, or the team has never run projections. | Regulators or the domain need a complete, replayable history and overwrites lose facts you will be asked for. |
| Complexity | High: event schemas and versioning (upcasting), snapshots, projections, replay tooling, idempotent handlers, the discipline never to mutate history. | Low: a row is updated; the database enforces constraints. |
| Operational cost | An append-only store that grows forever, snapshotting, projection lag, rebuilds that replay millions of events. | Standard database operations; audit via triggers or a change-data-capture stream if needed. |
| Failure modes | A replay that no longer works because an old event shape was not upcast; crypto-shredding as the only way to "delete"; an aggregate with 2 million events and no snapshot. | Lost history on overwrite, a bug whose effect cannot be reconstructed, an audit table that drifts from the state it claims to describe. |
| Data flow | Command → validate against replayed state → append event → projections update | Request → UPDATE row → done |
| Consistency | Strong per aggregate (optimistic concurrency on the event version); eventual for projections | Transactional across whatever the transaction touches |
| Temporal queries | "What was the balance on 3 March" is a replay to that point | Only if you kept history explicitly |
| Relationship to CQRS | Almost always paired: the event log is the write side, projections are the read side | Independent; CQRS-lite works over plain state |