Event-Driven Architecture
Event-driven architecture makes the production and consumption of state changes the primary integration mechanism, so services react to what happened rather than calling each other and coupling.
Definition
Event-driven architecture is a pattern where services communicate by publishing and consuming events — facts about what has happened — rather than by direct calls, so that producers do not know their consumers, consumers react to history rather than querying current state, and the system is temporally decoupled.
Context and scope
Applied in async business processes, integration between bounded contexts, and any system where the cost of synchronous coupling outweighs the cost of eventual consistency.
Common misconceptions
- Events are just messages — events are facts; commands are requests; conflating them produces a system where consumers cannot tell what they are allowed to reject
- Event-driven is always more decoupled — producers are decoupled from consumers, but the event schema becomes the coupling, and its evolution is the hard part
Anti-patterns
- Publishing commands as events and expecting consumers to refuse them, when the event semantics say they are facts that cannot be refused
- Designing events so specific to the producer that every consumer change requires a producer change, recreating the coupling events were meant to remove
Related concepts
Authoritative source
https://martinfowler.com/articles/20110607EventDrivenCollaboration.html
What it is
Event-driven architecture is a pattern where services communicate by publishing and consuming events — facts about what has happened — rather than by direct calls, so that producers do not know their consumers, consumers react to history rather than querying current state, and the system is temporally decoupled. Applied in async business processes, integration between bounded contexts, and any system where the cost of synchronous coupling outweighs the cost of eventual consistency. The organizing principle is which decisions are hard to reverse and should be made once, versus which are easy to reverse and should be deferred.
How it works
Boundaries are drawn along axes of change: things that change together are colocated, things that change independently are separated by interfaces whose contracts are explicit and versioned. Dependencies point toward stability — domain logic depends on abstractions, infrastructure depends on domain, never the reverse. The structure makes the system’s intent legible without reading every module.
When to choose and pitfalls
Choose this structure when the system will outlive its first deployment and face requirements you cannot now predict. The pitfall is premature abstraction — adding indirection for a flexibility that never materializes, paying its complexity cost forever. The opposite pitfall is entangling concerns that later need to separate, forcing a rewrite instead of a refactor.