Martin Fowler’s presentation on Event-Driven Architecture (EDA) highlights the varied interpretations of “event-driven” and categorizes them into four distinct patterns to provide more precision in software development discussions. He begins by noting that while the term “event-driven” is commonly used, its specific meaning often varies, leading to confusion. To address this, a workshop was held to identify and define common patterns, resulting in the four patterns discussed in the talk.
1. Event Notification
This is the most common pattern.
- Systems use events to notify other systems about a change.
- The source system does not need to know what downstream systems will do with the event.
Example
- Event: “Customer address changed”
Benefits
- Decouples systems.
- New consumers can subscribe to events without modifying the producer.
- Enables flexibility and easier integration.
Event vs Command
- Event
- States that something already happened.
- Example: “Customer address changed”
- Command
- Requests something to happen.
- Example: “Re-quote insurance for this customer”
Drawback
- Harder to understand the overall system flow.
- There is no central code controlling what happens after an event.
- Debugging requires tracing message flows, similar to debugging a complex GUI event system.
2. Event-Carried State Transfer
This pattern extends Event Notification. Instead of only notifying that something changed, the event includes the actual data (state).
Example
Instead of:
CustomerAddressChanged
The event carries:
CustomerAddressChanged
{
customerId
newAddress
}
Key Idea
- Events contain both the notification and the data.
Benefits
- Downstream systems can keep a local copy of required data.
- Reduces or eliminates direct API calls to the source system.
- Improves:
- Performance
- Availability
- Scalability
Advantages
- Fewer remote calls
- Less load on source system
- Systems can function even if the source system is temporarily unavailable
Trade-offs
- Eventual consistency
- Data across systems may not be immediately synchronized.
- Data duplication
- More complexity in maintaining consistency over time
3. Event Sourcing
Event Sourcing changes how application state is stored. Instead of storing the current state, the system stores a sequence of events representing every change. The current state can be reconstructed by replaying these events.
Conceptual Comparisons
- Git
- Current codebase is derived from a sequence of commits.
- Accounting ledgers
- Balance is calculated from credits and debits.
Advantages
- Complete audit trail
- Every change is recorded.
- Powerful debugging
- Replay events to understand how a state was reached.
- Time travel
- View application state at any moment in the past.
- Memory image systems
- Event log becomes the permanent storage.
- Application state can stay entirely in memory for performance.
- Used in systems like LMAX.
Challenges
- Unfamiliar mental model
- Developers must think differently about persistence.
- External system interactions
- Responses from external systems must also be recorded as events to allow replay.
- Event schema versioning
- Event structures evolve over time.
- Older events must still work with newer code.
- Asynchronous processing
- Not mandatory, but often used, which adds complexity. Greg Young - Event Sourcing
4. CQRS (Command Query Responsibility Segregation)
CQRS separates read operations and write operations into different models.
Core Idea
- Commands → Modify data
- Queries → Read data Each side uses different models, and sometimes different databases.
Command Model
- Handles business logic
- Focused on data modification
Query Model
- Optimized for efficient data retrieval
- Designed specifically for reading operations
Key Rule (Greg Young’s definition)
- The command model is never used for reading.
- All reads must go through the query model. Even reads needed during command processing should use the query side.
Benefit
This strict separation allows:
- Independent optimization of write logic
- Independent optimization of read performance
Conclusion
Martin Fowler emphasizes that understanding these four patterns provides a more precise vocabulary when discussing event-driven systems. The four patterns are:
- Event Notification
- Event-Carried State Transfer
- Event Sourcing
- CQRS Using these distinctions helps developers:
- Identify appropriate architectural techniques
- Anticipate potential challenges
- Make more informed design decisions This precision is similar to how the term “microservices” offers a clearer definition within the broader concept of service-oriented architecture.