Event-Driven Architecture
Event-driven architecture (EDA) centers on producing, routing, and consuming events — immutable records that something happened (OrderPlaced, PaymentCaptured, DriverLocationUpda…
Introduction
Event-driven architecture (EDA) centers on producing, routing, and consuming events — immutable records that something happened (OrderPlaced, PaymentCaptured, DriverLocationUpdated). Producers don't know consumers; the event broker decouples teams and absorbs traffic spikes.
EDA excels at fan-out (one order triggers email, analytics, warehouse, loyalty), temporal decoupling, and audit trails. Trade-offs include eventual consistency, duplicate delivery handling, and debugging complexity across async flows.
This lesson teaches event naming, broker selection, consumer design, and how EDA complements request-response APIs in HLD interviews.
Understanding the topic
Key concepts
- Event: past-tense fact with schema (Avro/JSON Schema/Protobuf) and metadata (timestamp, correlationId).
- Event notification vs event-carried state transfer — choose based on consumer autonomy.
- Broker: Kafka for log-based replay; RabbitMQ/SQS for task queues; Redis Streams for lighter cases.
- At-least-once delivery typical — consumers must be idempotent.
- CQRS often pairs with EDA: write model emits events; read models project asynchronously.
- Choreography (consumers react) vs orchestration (central saga coordinator).
flowchart LRProducer -->|event| BrokerBroker --> ConsumerABroker --> ConsumerB
Internal architecture
Architecture overview
flowchart LRProducer -->|event| BrokerBroker --> ConsumerABroker --> ConsumerB
Step-by-step explanation
- Command API accepts user action → persists aggregate → publishes domain event to broker.
- Topic partitioned by aggregate ID (orderId) preserving per-entity ordering.
- Multiple consumer groups read same topic independently (notifications vs BI).
- Dead-letter queue (DLQ) captures poison messages after retry exhaustion.
- Schema registry enforces compatible event evolution.
- Observability: trace context propagated in event headers (OpenTelemetry baggage).
Informative example
Publish inventory adjustment events after stock update — downstream search index updates asynchronously:
@Servicepublic class InventoryService {private final InventoryRepository repo;private final KafkaTemplate<String, StockAdjustedEvent> kafka;public InventoryService(InventoryRepository repo, KafkaTemplate<String, StockAdjustedEvent> kafka) {this.repo = repo;this.kafka = kafka;}@Transactionalpublic void adjust(String sku, int delta) {Inventory inv = repo.findBySku(sku).orElseThrow();inv.apply(delta);repo.save(inv);kafka.send("inventory.stock-adjusted", sku,new StockAdjustedEvent(sku, inv.quantity(), Instant.now()));}}public record StockAdjustedEvent(String sku, int quantity, Instant at) {}@Componentclass SearchIndexConsumer {@KafkaListener(topics = "inventory.stock-adjusted", groupId = "search-index")public void project(StockAdjustedEvent e) {// upsert Elasticsearch document — idempotent by sku}}
Name events in past tense. Include correlationId from HTTP request in Kafka headers for end-to-end traces.
Real-world use
Real-world use cases
- E-commerce order pipeline fan-out to warehouse, email, fraud, analytics.
- Banking ledger posting triggering compliance audit and customer notification.
- Social graph: new post event updates follower feeds and search index.
- Healthcare HL7/FHIR change events syncing EHR modules.
Best practices
- Design idempotent consumers with natural keys or idempotency store.
- Version event schemas with backward-compatible rules.
- Use outbox pattern to atomically DB-write + publish.
- Monitor consumer lag — primary EDA health metric.
- Keep events small; reference large blobs by URL/id.
- Document event catalog — who publishes, who subscribes, SLA.
Common mistakes
- Using events for synchronous query/response — wrong tool.
- No DLQ — poison messages block partition processing.
- Assuming exactly-once without transactional outbox or idempotent design.
- God topics with unrelated events — hard to scale and govern.
- Missing ordering guarantees where business requires per-entity sequence.
Advanced interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1BeginnerQuestionWhat is event-driven architecture?+
Answer
2BeginnerQuestionBenefit of EDA over direct HTTP calls?+
Answer
3IntermediateQuestionHow handle duplicate events?+
Answer
4IntermediateQuestionOutbox pattern purpose?+
Answer
5AdvancedQuestionDesign EDA for food order lifecycle.+
Answer
Summary
EDA decouples services through immutable domain events. Kafka enables replay, fan-out, and high-throughput logs. Design for at-least-once with idempotent consumers. Outbox pattern bridges transactional writes and publishing. Pair events with CQRS for read model projections. Layered and scaling lessons build on these integration patterns.