#architecture#event-driven#backend

Event-Driven Architecture: Building Reactive Systems

Explore event-driven architecture patterns including event sourcing, CQRS, and message queues for building responsive and scalable applications.

2 min read
Table of Contents

Why Event-Driven?

Traditional request-response architectures work well for simple applications. But as systems grow, they become tightly coupled and difficult to scale. Event-driven architecture (EDA) offers a different approach.

Core Concepts

Events vs Commands

An event describes something that happened. A command requests something to happen.

// Event - past tense, immutable fact
interface OrderPlaced {
  type: "OrderPlaced";
  orderId: string;
  items: Item[];
  timestamp: Date;
}

// Command - imperative, can be rejected
interface PlaceOrder {
  type: "PlaceOrder";
  items: Item[];
  customerId: string;
}

CQRS (Command Query Responsibility Segregation)

Separate your read and write models:

// Write side - handles commands
class OrderCommandHandler {
  handle(cmd: PlaceOrder) {
    const order = Order.create(cmd);
    this.eventStore.append(order.events);
  }
}

// Read side - optimized for queries
class OrderQueryHandler {
  getOrderSummary(orderId: string) {
    return this.readDb.query(
      "SELECT * FROM order_summaries WHERE id = ?",
      [orderId]
    );
  }
}

Message Queues

Message queues decouple producers from consumers:

  • Apache Kafka - High throughput, log-based
  • RabbitMQ - Flexible routing, AMQP protocol
  • Redis Streams - Lightweight, in-memory

When to Use EDA

Use event-driven architecture when:

  • Multiple services need to react to the same event
  • You need audit trails or time-travel debugging
  • System components have different scaling requirements
  • You want to decouple teams and services

Avoid when:

  • Simple CRUD operations suffice
  • Strong consistency is required everywhere
  • The team is small and the system is straightforward