🚀 Event-Driven Architecture (EDA)
The Senior Mindset: EDA is a paradigm shift from Commands (“Do this”) to Events (“This happened”). A senior engineer uses EDA to build systems that are highly reactive, extensible, and capable of handling massive spikes in load by processing data asynchronously.
🏗️ Core Concepts
Section titled “🏗️ Core Concepts”1. The Event
Section titled “1. The Event”An immutable record of a past action. It contains the “State” or the “Change” that occurred.
- Example:
OrderPlaced,UserRegistered,PaymentFailed.
2. Producers & Consumers
Section titled “2. Producers & Consumers”- Producer: The service that detects a change and publishes an event. It doesn’t know (or care) who consumes it.
- Consumer: The service that listens for specific events and reacts to them.
3. Channels (The Broker)
Section titled “3. Channels (The Broker)”The infrastructure that carries events.
- Message Queues: (e.g., RabbitMQ) Usually point-to-point; once a message is consumed, it’s gone.
- Event Streams: (e.g., Kafka) A continuous log of events that can be replayed.
🛠️ Communication Patterns
Section titled “🛠️ Communication Patterns”Pub/Sub (Publish/Subscribe)
Section titled “Pub/Sub (Publish/Subscribe)”One producer sends a message that multiple consumers can receive.
- Use Case: An
OrderPlacedevent triggers the Shipping Service, the Email Service, and the Inventory Service simultaneously.
Event Streaming
Section titled “Event Streaming”Events are stored in an ordered log. Consumers can read the stream at their own pace.
- Consumer Groups: Allow you to parallelize processing by spreading the stream across multiple instances.
⚖️ The Benefits & Challenges (The Senior Perspective)
Section titled “⚖️ The Benefits & Challenges (The Senior Perspective)”The “Pros”
Section titled “The “Pros””- Extreme Decoupling: Adding a new feature (like a “Loyalty Points” service) doesn’t require touching the “Order” service code. You just subscribe to the existing events.
- Resilience: If the Email Service is down, the events wait in the broker. When the service comes back online, it processes the backlog without losing data.
- Scalability: You can scale consumers independently based on the volume of specific events.
The “Cons” (The Senior Tax)
Section titled “The “Cons” (The Senior Tax)”- Eventual Consistency: Data isn’t updated everywhere instantly. You must design the UI and business logic to handle “in-flight” states.
- Tracing & Debugging: It’s harder to follow a single “user journey” when it’s scattered across five services and a broker. (Solution: Use Correlation IDs).
- Duplicate Events: Network issues can cause events to be sent twice.
🛡️ Critical Design Patterns
Section titled “🛡️ Critical Design Patterns”1. Idempotency
Section titled “1. Idempotency”Because “exactly-once” delivery is nearly impossible in distributed systems, every consumer must be idempotent.
- Senior Strategy: Processing the same event twice should have the same result as processing it once (e.g., checking if a Transaction ID already exists in the DB before processing a payment).
2. The Outbox Pattern
Section titled “2. The Outbox Pattern”How do you ensure that a Database update and an Event publication both happen (or both fail)?
- The Problem: You save to the DB, but the broker is down. Now the DB is updated, but the rest of the system is out of sync.
- The Solution: Save the event in a dedicated
Outboxtable in the same DB transaction as your business data. A separate “Relay” process polls that table and publishes to the broker.
3. Dead Letter Queues (DLQ)
Section titled “3. Dead Letter Queues (DLQ)”When a consumer fails to process an event (e.g., due to a malformed payload), don’t let it block the whole queue.
- Strategy: Move the “poison pill” message to a DLQ for manual inspection and let the consumer move on to the next event.
⚡ Event Sourcing & CQRS
Section titled “⚡ Event Sourcing & CQRS”- Event Sourcing: Instead of storing the current state of an object, you store every single event that led to that state. To get the balance of a bank account, you replay all
DepositandWithdrawalevents. - CQRS (Command Query Responsibility Segregation): Separating the “Write” model (Events) from the “Read” model (Optimized materialized views).
💡 Seniority Note: Don’t go “Full Event-Driven” for everything. It introduces massive cognitive load. Use Request/Response for synchronous, user-facing actions where an immediate “Success/Fail” is needed. Use EDA for side effects, background processing, and inter-service communication.
🔗 Related Links
Section titled “🔗 Related Links”- [[Messaging-Kafka-vs-RabbitMQ]]
- [[Microservices-Patterns]]
- [[Architecture-Resilience-Patterns]]