Event-Driven System Design
Event-driven architecture (EDA) is powerful but often misunderstood. Here's the reality.
Event-driven architecture (EDA) is powerful but often misunderstood. Here's the reality.
When Event-Driven Makes Sense
Choose event-driven when:
- You have asynchronous workflows that don't require immediate consistency
- You need to decouple producers from consumers
- You're building event-sourced systems or audit trails
- You're integrating with external systems via events
Stay message-driven or synchronous when:
- You need strong consistency guarantees
- Workflows are predominantly synchronous
- Debugging distributed event flows is too complex for your team
- You're processing simple CRUD operations
Key Concepts
Events vs. Commands
- Events: Something happened in the past. Past-tense, factual. "OrderPlaced", "UserRegistered".
- Commands: Something should happen in the future. Present-tense, intent. "PlaceOrder", "RegisterUser".
Publish-Subscribe
One-to-many. One publisher, many potential consumers. Consumers process what they care about and ignore the rest.
Point-to-Point
One-to-one. One publisher, one consumer. The message is processed exactly once (or at least once).
Event Schema Design
- Version events: Include a version number in your event schema. Future you will thank present you.
- Avoid payload bloat: Only include essential data in events. Put additional data in a lookup service if needed.
- Schema evolution: Plan for how events will change over time. Backward compatibility is your friend.
Common Pitfalls
Anti-pattern 1: Using Events for Synchronous Workflows
The mistake: Publishing an event and then waiting for a response, effectively making it synchronous.
The fix: If you need a response, use a command-response pattern or make it truly asynchronous with a correlation ID and timeout.
Anti-pattern 2: Anemic Event Payloads
The mistake: Including only a type and ID in events, forcing consumers to fetch additional data from a database.
The fix: Include sufficient context in the event payload. What does the consumer need to know to process this event?
Anti-pattern 2: Tight Coupling Through Events
The mistake: Designing events that couple producers and consumers too tightly.
The fix: Define clear event contracts. Producers shouldn't need to know which consumers exist or their implementation details.
Anti-pattern 3: Event Storming Without Direction
The mistake: Generating too many events without a clear understanding of the business domain.
The fix: Start with domain-driven design. Identify your aggregates, commands, and events before designing the messaging system.
Event Sourcing vs. Event-Driven Architecture
These are related but different:
- Event-driven architecture: Events communicate between services/systems. The system state may be stored traditionally.
- Event sourcing: The system state is derived from a sequence of events. The event log IS the source of truth.
You can have event-driven architecture without event sourcing. You can have event sourcing without full event-driven architecture. Understand the distinction.
The Honest Truth
Event-driven architecture introduces significant complexity in debugging, testing, and understanding system behavior. It's the right choice for certain domains (audit trails, asynchronous workflows, CQRS scenarios) but wrong for others (simple CRUD, strong consistency requirements).
The decision should be based on your specific constraints, not industry hype.
Published June 1, 2026 · 16 min read