Event-Driven Architecture
Overview
Event-Driven Architecture (EDA) is an architectural pattern where system components communicate through the production, detection, and consumption of events. This pattern enables loose coupling, scalability, and real-time processing.
Core Concepts
What is an Event?
An event is a significant change in state or an occurrence that happened at a specific point in time.
Event Characteristics:
- Immutable - Events represent facts that cannot be changed
- Timestamped - Events capture when something happened
- Contextual - Events contain relevant information about what happened
- Decoupled - Event producers don’t know who consumes the event
Event Types
1. Domain Events
Events that represent business-meaningful occurrences:
OrderPlacedPaymentProcessedInventoryUpdatedCustomerRegistered
2. Integration Events
Events used for cross-system communication:
OrderShipped(triggers notification service)ProductPriceChanged(updates catalog service)
3. System Events
Technical events for infrastructure concerns:
ServiceStartedThresholdExceededErrorOccurred
Architecture Patterns
1. Event Notification
Pattern: Publisher sends lightweight event notifications; consumers request details if interested.
When to Use:
- Loose coupling is priority
- Consumers need different levels of detail
- Network bandwidth considerations
Example:
OrderService → OrderPlaced(orderId) → [Notification, Analytics, Warehouse]
Each service fetches order details as needed
2. Event-Carried State Transfer
Pattern: Event contains all necessary data; consumers maintain local copies.
When to Use:
- Reduce coupling between services
- Improve query performance
- Eventual consistency is acceptable
Example:
ProductService → ProductUpdated(fullProductData) → [Catalog, Recommendation, Search]
Each service stores product data locally
3. Event Sourcing
Pattern: Store all changes as sequence of events; current state is derived from event history.
When to Use:
- Audit trail required
- Time-travel queries needed
- Complex domain logic
- CQRS implementation
Benefits:
- Complete audit history
- Temporal queries
- Event replay for debugging
- Natural fit for CQRS
Challenges:
- Event schema evolution
- Storage requirements
- Query complexity
4. CQRS (Command Query Responsibility Segregation)
Pattern: Separate read and write models; often combined with event sourcing.
Components:
- Command Model - Handles writes, validates business rules
- Query Model - Optimized read models, eventually consistent
- Events - Synchronize command and query models
Benefits:
- Optimized read and write models
- Scalability
- Flexibility in data storage
Key Components
Event Producer
Component that detects and publishes events.
Responsibilities:
- Detect state changes
- Create event messages
- Publish to event bus
- Handle failures
Best Practices:
- Use consistent event naming
- Include correlation IDs
- Version events from start
- Keep events immutable
Event Consumer
Component that subscribes to and processes events.
Processing Patterns:
Competing Consumers
Multiple instances process from same queue:
EventBus → Queue → [Consumer1, Consumer2, Consumer3]
- Load balancing
- Scalability
- At-least-once delivery
Publish-Subscribe
Each subscriber receives copy:
EventBus → Topic → [SubscriberA, SubscriberB, SubscriberC]
- Multiple independent consumers
- Fan-out pattern
- Each gets all events
Best Practices:
- Idempotent processing
- Handle duplicates
- Dead letter queues
- Retry strategies
Event Bus/Broker
Infrastructure for routing events from producers to consumers.
Options:
- Apache Kafka - High throughput, distributed log
- RabbitMQ - Feature-rich message broker
- AWS SNS/SQS - Cloud-native pub/sub
- Azure Event Grid - Serverless event routing
- Azure Service Bus - Enterprise messaging
- Google Cloud Pub/Sub - Global messaging
Implementation Patterns
Saga Pattern
Manage distributed transactions across services using events.
Choreography Saga:
OrderService → OrderCreated →
PaymentService → PaymentProcessed →
InventoryService → InventoryReserved →
ShippingService → OrderShipped
Orchestration Saga:
SagaOrchestrator coordinates:
1. Create Order
2. Process Payment
3. Reserve Inventory
4. Ship Order
Compensation:
- Define compensating transactions
- Handle partial failures
- Maintain saga state
Outbox Pattern
Ensure reliable event publishing with database transactions.
Flow:
- Business transaction updates database
- Insert event into outbox table (same transaction)
- Background process publishes events
- Mark events as published
Benefits:
- Transactional consistency
- At-least-once delivery
- No dual-write problem
Inbox Pattern
Ensure idempotent event processing.
Flow:
- Receive event
- Check inbox for duplicate (by event ID)
- If new, process and record in inbox
- If duplicate, skip processing
Event Schema Design
Schema Structure
{
"eventId": "uuid",
"eventType": "OrderPlaced",
"eventVersion": "1.0",
"timestamp": "2025-11-12T10:30:00Z",
"correlationId": "order-123",
"causationId": "previous-event-id",
"source": "order-service",
"data": {
"orderId": "123",
"customerId": "456",
"totalAmount": 99.99,
"items": [...]
},
"metadata": {
"userId": "789",
"sessionId": "xyz"
}
}
Schema Evolution
Strategies:
- Add Only - Only add optional fields
- Versioning - Use semantic versioning
- Transformation - Upcasting old events
- Schema Registry - Centralized schema management
Best Practices:
- Never remove fields
- Make new fields optional
- Document breaking changes
- Support multiple versions
Event Ordering
Ordering Guarantees
Global Ordering:
- All events ordered system-wide
- Difficult to scale
- Rarely needed
Partition Ordering:
- Events for same key ordered
- Kafka partitions
- SQS FIFO queues
- Scalable approach
No Ordering:
- Maximum scalability
- Application handles ordering
- Design for eventual consistency
Handling Out-of-Order Events
Techniques:
- Version Numbers - Track entity versions
- Timestamps - Compare event times
- Causal Ordering - Track event dependencies
- Sequence Numbers - Partition-level ordering
Error Handling
Retry Strategies
Exponential Backoff:
Retry 1: 1 second
Retry 2: 2 seconds
Retry 3: 4 seconds
Retry 4: 8 seconds
Circuit Breaker:
- Stop retrying after threshold
- Prevent cascade failures
- Periodic recovery attempts
Dead Letter Queues
Purpose:
- Store failed messages
- Manual intervention
- Analysis and debugging
When to DLQ:
- Exceeded retry limit
- Poison messages
- Schema validation failures
Monitoring & Observability
Key Metrics
Event Metrics:
- Event production rate
- Event consumption rate
- Processing latency
- Error rates
- Queue depth
Business Metrics:
- Events by type
- Processing time by event type
- Failed events by reason
Distributed Tracing
Correlation:
- Trace events across services
- Correlation IDs
- Causation IDs
- OpenTelemetry integration
Visualization:
- Event flow diagrams
- Latency analysis
- Bottleneck identification
Testing Strategies
Unit Testing
- Test event creation
- Test event handlers in isolation
- Mock event bus
Integration Testing
- Test event flow
- Test with real message broker
- Verify ordering guarantees
Contract Testing
- Verify event schemas
- Consumer-driven contracts
- Schema compatibility testing
Chaos Engineering
- Simulate message loss
- Test duplicate handling
- Verify compensation logic
Best Practices
Design Principles
- Events are Facts - Immutable, past tense
- Single Responsibility - One event per business occurrence
- Self-Contained - Include necessary context
- Versioned - Support evolution
- Correlated - Traceable across services
Operational Excellence
- Monitoring - Comprehensive event tracking
- Alerting - Detect anomalies quickly
- Replay Capability - Recover from failures
- Schema Registry - Centralized management
- Documentation - Document all events
Common Pitfalls
❌ Event Coupling - Events too specific to consumers ❌ God Events - Events containing everything ❌ Missing Idempotency - Not handling duplicates ❌ Ignoring Ordering - Assuming global order ❌ No Versioning - Breaking changes without migration ❌ Synchronous Mindset - Expecting immediate consistency
Use Cases
E-commerce Platform
- Order processing
- Inventory management
- Payment processing
- Shipping notifications
IoT Systems
- Sensor data streaming
- Real-time analytics
- Alert processing
- Device state management
Financial Services
- Transaction processing
- Fraud detection
- Audit logging
- Market data distribution
Social Media
- Activity streams
- Notifications
- Content distribution
- Analytics
Migration Strategies
Strangler Fig Pattern
- Identify bounded context
- Introduce event bus
- Dual-write events
- Migrate consumers gradually
- Remove old integration
Event Interception
- Intercept database changes (CDC)
- Publish as events
- Gradual consumer adoption
- Eventual removal of interception
Tools & Technologies
Message Brokers
- Apache Kafka - Distributed streaming platform
- RabbitMQ - AMQP message broker
- NATS - Cloud-native messaging
- Apache Pulsar - Multi-tenant messaging
Cloud Services
- AWS EventBridge - Serverless event bus
- AWS SNS/SQS - Pub/sub and queuing
- Azure Event Grid - Event routing
- Azure Service Bus - Enterprise messaging
- Google Cloud Pub/Sub - Global messaging
Frameworks
- Spring Cloud Stream - Event-driven microservices
- MassTransit - .NET message bus
- NServiceBus - Enterprise service bus
- Axon Framework - Event sourcing & CQRS
Related Resources
References
- Enterprise Integration Patterns by Gregor Hohpe
- Building Event-Driven Microservices by Adam Bellemare
- Designing Data-Intensive Applications by Martin Kleppmann
- AWS Event-Driven Architecture
- Azure Event-Driven Architecture
Last Updated: November 2025
Related: Microservices | DDD | Integration Patterns