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
A producer announces what happened and does not know who listens; a caller asks a specific service and waits for the answer. Events give loose coupling and fan-out; requests give immediacy and a clear failure. Most systems use both: a synchronous command, asynchronous consequences.
| Event-driven Event-Driven Architecture | Request/response Request/Response vs Event-Driven | |
|---|---|---|
| Use when | Many consumers react to the same fact, work can happen later, load is bursty, and the producer must not depend on consumer availability. | The caller needs the answer now, the dependency chain is short, and a failure must surface to the caller immediately. |
| Avoid when | You need read-your-writes, the handlers are not idempotent, or nobody owns the answer to "who owns the truth" for the event. | Every user request fans out into a chain of five services, each waiting on the next, with timeouts that do not nest. |
| Complexity | High: brokers, schemas, ordering, duplicates, eventual consistency, replay, and tracing across asynchronous hops. | Low: a call, a timeout, an error; easy to reason about, easy to test. |
| Operational cost | A broker, consumer-lag monitoring, dead-letter handling, a schema registry or discipline in its place. | None beyond the services themselves; the cost is availability coupling. |
| Failure modes | Invisible backlog, stale read models, events delivered twice or out of order, a consumer that silently never runs, and debugging that requires reconstructing time from offsets. | Cascading latency, retry storms, one slow dependency exhausting shared pools, availability multiplying down the chain. |
| Data flow | Service writes state + outbox → relay publishes → consumers update their own state | Caller → callee → caller, one hop per dependency |
| Consistency | Eventual across services; strong inside each | Strong along the call, at the price of coupling |
| Observability | Trace context must ride inside the message headers; lag is the key metric | Trace context rides in HTTP headers; latency histograms per hop |
| Team shape | Producers and consumers evolve independently under a schema contract | Caller and callee coordinate on the API and its versions |