All Articles
ArchitecturePlatform EngineeringCloud Architecture

Event-Driven Architecture: When and How to Use It

Event-driven architecture enables loose coupling, scalability, and real-time processing. Here are the patterns, the technology choices, and the honest assessment of when EDA is the right choice — and when it's overkill.

MG
Mohamed Ghassen Brahim
May 4, 202610 min read

Event-driven architecture (EDA) is one of the most powerful — and most over-applied — architectural patterns. When used correctly, it enables loose coupling, independent scalability, and real-time responsiveness. When used incorrectly, it introduces debugging nightmares, eventual consistency headaches, and unnecessary complexity.

Here's how to use EDA effectively.

What Event-Driven Architecture Is

In traditional request-response architecture, services call each other directly. Service A sends a request to Service B, waits for a response, and continues.

In event-driven architecture, services communicate by producing and consuming events. Service A publishes an event ("order placed"). Service B, C, and D consume that event independently and act on it — without Service A knowing or caring what they do with it.

The fundamental shift: From "tell a specific service to do something" to "announce that something happened and let interested services react."

Event Types

Domain Events

Facts about something that happened in your business domain. Immutable. Past tense.

Examples: OrderPlaced, PaymentProcessed, UserRegistered, InventoryReserved

Characteristics: Named as past-tense verbs. Contain the relevant data at the time of the event. Cannot be changed after emission.

Integration Events

Events published specifically for cross-service communication. Similar to domain events but designed for external consumers.

Commands

Requests for a specific action. Future tense. Directed at a specific service.

Examples: ProcessPayment, SendNotification, ReserveInventory

Key difference from events: Commands are directed at a specific consumer. Events are broadcast to all interested consumers.

Patterns

Pattern 1: Event Notification

The simplest pattern. A service publishes a lightweight event (type + ID, minimal data). Consumers query back for full details if needed.

Example:

{
  "type": "OrderPlaced",
  "orderId": "ord-123",
  "timestamp": "2026-05-04T10:30:00Z"
}

Pros: Loose coupling. Events are small. Simple to implement. Cons: Consumers need to call back for data (extra network calls, coupling through queries).

Pattern 2: Event-Carried State Transfer

Events carry all the data the consumer needs. No callback required.

Example:

{
  "type": "OrderPlaced",
  "orderId": "ord-123",
  "customerId": "cust-456",
  "items": [{"sku": "WIDGET-1", "quantity": 2, "price": 29.99}],
  "total": 59.98,
  "timestamp": "2026-05-04T10:30:00Z"
}

Pros: No callbacks needed. Consumers are fully independent. Better for high-throughput systems. Cons: Larger events. Data duplication across services. Risk of stale data if consumers cache event data.

Pattern 3: Event Sourcing

Instead of storing current state, store the sequence of events that led to the current state. The current state is derived by replaying events.

Example: An account's balance isn't stored as a number. It's calculated by replaying all MoneyDeposited and MoneyWithdrawn events.

Pros: Complete audit trail. Can reconstruct state at any point in time. Natural fit for financial and compliance applications. Cons: Complex to implement. Read performance requires projections. Mental model shift for developers.

Pattern 4: CQRS (Command Query Responsibility Segregation)

Separate the write model (commands) from the read model (queries). Often combined with event sourcing.

When it works: When read and write patterns are fundamentally different (e.g., writes are transactional, reads are analytical). When you need different data models optimised for different query patterns.

When it's overkill: Simple CRUD applications. Systems where read and write patterns are similar.

Technology Choices

TechnologyTypeStrengthsBest For
Apache KafkaDistributed logHigh throughput, durability, replayHigh-volume event streaming
Azure Event HubsManaged streamingAzure-native, easy setup, Kafka-compatibleAzure-centric, managed
AWS EventBridgeServerless event busSchema registry, filtering, routingAWS-centric, serverless
RabbitMQMessage brokerFlexible routing, simple, matureModerate volume, complex routing
Azure Service BusEnterprise messagingTransactions, sessions, dead-letterEnterprise messaging patterns
Redis StreamsIn-memory streamingLow latency, simpleLow-latency, moderate volume
NATSCloud-native messagingLightweight, fast, simpleMicroservices, cloud-native

Decision Framework

  • Need replay capability? → Kafka, Event Hubs
  • Need complex routing? → RabbitMQ, Service Bus
  • Need serverless integration? → EventBridge
  • Need lowest latency? → Redis Streams, NATS
  • Need enterprise features (transactions, dead-letter)? → Service Bus, RabbitMQ

Schema Evolution

As events evolve over time, you need backward and forward compatibility:

Rules for safe evolution:

  • You CAN add new optional fields
  • You CANNOT remove fields that consumers depend on
  • You CANNOT change field types
  • You CAN add new event types

Schema Registry: Use a schema registry (Confluent Schema Registry, Azure Schema Registry) to enforce compatibility. Every event is validated against its schema before publication.

Handling Distributed Transactions: The Saga Pattern

In event-driven systems, you can't use traditional database transactions across services. Instead, use the Saga pattern:

Choreography: Each service publishes events that trigger the next step. No central coordinator.

OrderService → OrderPlaced → PaymentService → PaymentProcessed → InventoryService → InventoryReserved → ShippingService

If any step fails, compensating events undo the previous steps:

InventoryService → InventoryReservationFailed → PaymentService → PaymentRefunded → OrderService → OrderCancelled

Orchestration: A central saga orchestrator directs each step and handles failures.

Choose choreography for simple flows (3-4 steps). Choose orchestration for complex flows (5+ steps, conditional logic, error handling).

When EDA Is Overkill

  • Simple CRUD applications with straightforward request-response patterns
  • Synchronous user interactions where the user expects immediate confirmation
  • Small teams without the operational expertise to manage event infrastructure
  • Low traffic systems where the complexity of EDA outweighs the scalability benefit
  • Tightly coupled workflows where every step must succeed synchronously

When EDA Is the Right Choice

  • Multiple consumers need to react to the same business event
  • Independent scalability — different services have different load patterns
  • Loose coupling is a priority (services evolve independently)
  • Real-time processing — react to events as they happen
  • Audit requirements — maintain a complete event history
  • Integration — connecting systems from different teams or vendors

Event-driven architecture is a powerful tool when applied to the right problems. If you're designing an event-driven system or evaluating whether EDA is right for your architecture, let's talk.

Ready to act

Ready to put this into practice?

I help companies implement the strategies discussed here. Book a free 30-minute discovery call.

Schedule a Free Call