Anti-patterns in event-driven architecture

Scope of experiences

  • Many commenters have long-running event-driven systems; others report outright disasters.
  • Domains with notable success: insurance and regulated industries (audit trails), banking and trading, manufacturing, public transport ticketing, some embedded systems, and especially games.
  • Several note heavy internal use of event concepts inside databases, VCS, and JS/GUI apps, even when the “architecture” isn’t branded as EDA.

Where event-driven shines

  • Integration across product suites and heterogeneous systems.
  • Moving slow or unreliable operations off the user’s critical path (emails, settlements, notifications, config distribution).
  • Domains that naturally produce “facts” over time and need full history, replay, or audit (ledgers, ticketing, some analytics).
  • Game dev and complex async systems where evented state machines are a natural fit.
  • Command-driven systems using messages as async instructions, not as primary state, are seen as a pragmatic middle ground.

Common anti-patterns and failures

  • Overuse: applying EDA everywhere, including simple request/response flows that would be clearer as direct function calls or CRUD APIs.
  • “Vanity” or resume-driven architectures: complex Kafka/event-sourcing stacks where a monolith would suffice.
  • Modeling queries and tightly coupled workflows as events; using commands with multiple consumers; building distributed monoliths.
  • Poor contracts: inconsistent wire formats, weak schema/versioning discipline, and non-deterministic consumers make replay and evolution fragile.
  • Operational pain: Kafka and cloud queues introduce infra overhead, difficult local setups, laggy consumers, ordering headaches, and costly observability.
  • Debuggability: hard to trace who consumes what, why something didn’t happen, or where a bug arose; no easy “find usages” for events.

Design guidance and patterns

  • Start from business/SLA: “can they wait?” If not, prefer synchronous calls.
  • Treat events as immutable facts; commands as single-consumer imperatives; avoid events-for-queries.
  • Favor entity-centric modeling (“nouns over verbs”), with commands and events changing entity state.
  • Embrace additive-only changes, idempotent consumers, deterministic projectors, DLQs, and replay strategies; accept at-least-once semantics where appropriate.
  • Invest heavily in telemetry (trace IDs, distributed tracing, shared logging infrastructure).

Meta-consensus

  • EDA is powerful but unforgiving: it magnifies both good and bad design.
  • Many argue microservices plus EDA are over-applied; a well-structured monolith with selective async pieces often wins on cost, simplicity, and time-to-market.