The Newspaper Analogy
Two communication styles:
Direct call (phone):
- You call each person individually
- They often need to be available right now
- 10 people = 10 calls
Newspaper (events):
- Publish your news once
- Anyone interested subscribes
- They read when convenient
- 10 or 10,000 readers - same effort!
Event-driven architecture is publishing, not calling.
What Is Event-Driven Architecture?
Components communicate by producing and consuming events.
Traditional (request-response):
Service A calls Service B directly.
A waits for B's response.
Tightly coupled.
Event-driven:
Service A publishes "OrderPlaced" event.
Services B, C, D consume it (if interested).
A doesn't wait. A doesn't know who listens.
Loosely coupled!
Core Concepts
Event
A record of something that happened.
{
"type": "OrderPlaced",
"timestamp": "<timestamp>",
"data": {
"orderId": "123",
"userId": "456",
"total": <total>
}
}
Past tense! "OrderPlaced" not "PlaceOrder"
Immutable fact.
Producer
Service that publishes events.
Order Service → publishes "OrderPlaced"
Doesn't know or care who consumes.
Consumer
Service that subscribes to events.
Inventory Service ← consumes "OrderPlaced"
Email Service ← consumes "OrderPlaced"
Analytics Service ← consumes "OrderPlaced"
Each handles the event independently.
Message Broker
Middleware that routes events.
Producers → Broker → Consumers
Examples: Kafka, RabbitMQ, AWS SNS/SQS
How It Works
Order placed:
┌────────────┐
│ Order │ ──→ "OrderPlaced" ──→ ┌───────────┐
│ Service │ │ Message │
└────────────┘ │ Broker │
└─────┬─────┘
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│Inventory │ │ Email │ │Analytics │
│ Service │ │ Service │ │ Service │
└──────────┘ └──────────┘ └──────────┘
Each service reacts independently.
Patterns
Publish-Subscribe (Pub/Sub)
One event → Multiple subscribers
OrderPlaced event:
- Inventory: Reduce stock
- Email: Send confirmation
- Analytics: Record sale
- Shipping: Create label
Add new subscriber without changing producer.
Event Streaming
Continuous stream of events.
Consumers process in real-time.
Example: User activity stream
Click → Scroll → Click → Purchase → ...
Kafka excels here.
Event Sourcing
Store events as source of truth.
Derive current state from event history.
(See Event Sourcing topic for details)
Benefits
1. Loose Coupling
Producer doesn't know consumers.
Add/remove consumers freely.
Services can be developed independently.
2. Scalability
Consumers can process events at their own pace.
High volume? Add more consumer instances.
Broker buffers when consumers are slow.
3. Resilience
Service down? Events wait in broker.
Service recovers? Processes backlog.
Less chance of data loss (when the broker is configured for durability).
4. Real-Time Reactions
Events propagate immediately.
Systems react in real-time.
Analytics, notifications, automation.
Challenges
1. Eventual Consistency
Events take time to propagate.
Consumer may be slightly behind producer.
Not a problem for most cases.
Challenge for strict consistency needs.
2. Debugging Complexity
Request-response: Clear call chain.
Event-driven: Events scatter across services.
Need distributed tracing.
Need event correlation IDs.
3. Ordering
Events may arrive out of order.
Consumer should handle, or the broker should provide ordering guarantees.
Partitioning can help (Kafka).
4. Event Schema Evolution
Events change over time.
Old consumers, new events. New consumers, old events.
Need versioning strategy.
When to Use
Good Fit
✓ Microservices needing to communicate
✓ Real-time data processing
✓ Async operations (email, notifications)
✓ Multiple services react to same event
✓ Scaling read/write independently
Might Be Overkill
✗ Simple CRUD applications
✗ Strong consistency requirements
✗ Single service applications
✗ Tight request-response needs
Popular Tools
| Tool | Type | Often Used For |
|---|---|---|
| Apache Kafka | Streaming platform | High volume, durability |
| RabbitMQ | Message broker | Traditional messaging |
| AWS SNS/SQS | Cloud messaging | AWS ecosystem |
| Redis Pub/Sub | In-memory | Simple, fast |
| NATS | Lightweight | Cloud native |
Common Mistakes
1. Fat Events
Event with entire object:
{ "order": { ...full order object... } }
Better: Include IDs, consumer fetches if needed.
Or: Just enough data for consumer's needs.
2. No Event Contracts
Producer changes event format.
Consumer breaks.
Define schemas (Avro, Protobuf, JSON Schema).
Version events.
3. Ignoring Failed Events
Event processing fails.
Event discarded.
Data lost!
Use dead letter queues.
Retry with backoff.
Alert on failures.
FAQ
Q: Event-driven vs message-driven?
Very similar! Message-driven focuses on the message exchange mechanism. Event-driven emphasizes domain events as the paradigm.
Q: How do I ensure events are processed once?
Idempotency! Design consumers to handle duplicate events safely.
Q: What about transactions across services?
Use Saga pattern for distributed transactions.
Q: Is Kafka the answer?
It depends. RabbitMQ is great for traditional messaging. Choose based on your needs.
Summary
Event-driven architecture enables loose coupling through asynchronous event communication.
Key Takeaways:
- Publish events, don't call directly
- Producers and consumers are decoupled
- Events stored/routed by message broker
- Enables scalability and resilience
- Eventually consistent (trade-off)
- Tools: Kafka, RabbitMQ, AWS SNS/SQS
Events are the glue that hold modern distributed systems together!
Related Concepts
Leave a Comment
Comments (0)
Be the first to comment on this concept.
Comments are approved automatically.