# Event-Driven Architecture

## 📚 สารบัญ

1. [หลักการพื้นฐาน](#หลักการพื้นฐาน)
2. [โครงสร้างของ Event-Driven](#โครงสร้างของ-event-driven)
3. [ข้อดี และข้อเสีย](#ข้อดี-และข้อเสีย)
4. [Event-Driven Patterns](#event-driven-patterns)
5. [Code Examples](#code-examples)
6. [Real World Examples](#real-world-examples)
7. [Best Practices](#best-practices)

---

## 🎯 หลักการพื้นฐาน

### Event-Driven Architecture คืออะไร?

**นิยาม:** สถาปัตยกรรมที่ components ติดต่อกันผ่าน events ซึ่ง:

- ✓ Producer (สร้าง events) ไม่รู้ว่า Consumer ใครนะ
- ✓ Events ไม่มี direct calls ระหว่าง components
- ✓ Loosely coupled
- ✓ Asynchronous communication
- ✓ Real-time or near real-time processing

### หลักการหลัก

```
1️⃣  Event Production
   - Component generates event
   - Not concerned with who listens
   - Just publishes to broker

2️⃣  Event Broker/Bus
   - Central mediator
   - Routes events to consumers
   - RabbitMQ, Kafka, Redis, AWS SNS

3️⃣  Event Consumption
   - Multiple consumers can listen
   - React to events
   - Independent of producer

4️⃣  Loose Coupling
   - Producer ไม่รู้ Consumer
   - Easy to add new consumers
   - Easy to modify existing ones

5️⃣  Asynchronous Processing
   - Non-blocking
   - Scalable
   - Better performance

6️⃣  Real-time Processing
   - Immediate reaction to events
   - Stream processing
   - Reactive systems
```

### Event-Driven vs Request/Response

```
REQUEST/RESPONSE (Traditional):
┌──────────────┐  "Give me user"  ┌──────────────┐
│   Client     │ ─────────────→  │   Server     │
│              │ ←───────────── │              │
│              │  "Here's user"   │              │
└──────────────┘                 └──────────────┘

- Synchronous (blocking)
- One-to-one
- Tight coupling
- Client waits for response

EVENT-DRIVEN:
┌──────────────┐  UserCreated  ┌──────────────┐
│   Producer   │ ─────────────→│  Event Bus   │
│              │                │              │
└──────────────┘                └────────┬─────┘
                                         │
                 ┌───────────────────────┼───────────────────┐
                 ↓                       ↓                   ↓
          ┌───────────────┐      ┌──────────────┐    ┌────────────────┐
          │ Email Service │      │Email Service │    │Analytics Service│
          │(Consumer 1)   │      │ (Consumer 2) │    │ (Consumer 3)   │
          └───────────────┘      └──────────────┘    └────────────────┘

- Asynchronous (non-blocking)
- One-to-many
- Loose coupling
- Producer doesn't wait
```

---

## 🏗️ โครงสร้างของ Event-Driven

### Typical Event-Driven Architecture

```
┌────────────────────────────────────────────────────────┐
│              EVENT PRODUCERS                            │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │ User Service │  │ Order Service│  │ Payment      │ │
│  │              │  │              │  │ Service      │ │
│  └──────────────┘  └──────────────┘  └──────────────┘ │
└────────────────────────────────────────────────────────┘
                           ↓
┌────────────────────────────────────────────────────────┐
│         EVENT BROKER / MESSAGE QUEUE                   │
│  ┌──────────────────────────────────────────────────┐ │
│  │  Topic: "user.registered"                        │ │
│  │  Topic: "order.created"                          │ │
│  │  Topic: "payment.completed"                      │ │
│  │                                                  │ │
│  │  (RabbitMQ, Kafka, Redis, AWS SNS/SQS)          │ │
│  └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
                           ↓
┌────────────────────────────────────────────────────────┐
│            EVENT CONSUMERS / HANDLERS                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │   Email      │  │   SMS        │  │ Notification│ │
│  │  Service     │  │  Service     │  │ Service     │ │
│  └──────────────┘  └──────────────┘  └──────────────┘ │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │
│  │  Analytics   │  │   Logging    │  │ Cache       │ │
│  │  Service     │  │  Service     │  │ Invalidator │ │
│  └──────────────┘  └──────────────┘  └──────────────┘ │
└────────────────────────────────────────────────────────┘
```

### Event Structure

```javascript
{
  "eventId": "evt_12345",
  "eventType": "order.created",
  "timestamp": "2025-12-27T10:30:00Z",
  "sourceSystem": "order-service",
  "version": "1.0",
  "data": {
    "orderId": 1001,
    "userId": 45,
    "items": [
      { "productId": 1, "quantity": 2, "price": 99.99 },
      { "productId": 5, "quantity": 1, "price": 49.99 }
    ],
    "total": 249.97,
    "shippingAddress": "123 Main St"
  },
  "correlationId": "corr_xyz789"
}
```

---

## ✅ ข้อดี และข้อเสีย

### ✅ ข้อดี

| ข้อดี                   | อธิบาย                       |
| ----------------------- | ---------------------------- |
| **Loose Coupling**      | Components ไม่รู้กันเอง      |
| **Scalability**         | Easy to add new consumers    |
| **Real-time**           | Immediate reaction to events |
| **Responsiveness**      | Better user experience       |
| **Parallel Processing** | Multiple handlers at once    |
| **Resilience**          | Failure ≠ system down        |
| **Event History**       | Can replay events            |
| **Audit Trail**         | All events logged            |

### ❌ ข้อเสีย

| ข้อเสีย                  | อธิบาย                          |
| ------------------------ | ------------------------------- |
| **Complexity**           | Hard to understand flow         |
| **Debugging**            | Difficult to trace              |
| **Testing**              | Async testing complex           |
| **Eventual Consistency** | Data not immediately consistent |
| **Event Ordering**       | Ensure correct order            |
| **Monitoring**           | Need sophisticated tools        |
| **Message Loss**         | Guarantee delivery              |
| **Learning Curve**       | Complex concepts                |

### เมื่อไดควรใช้ Event-Driven?

```
✅ ใช้เมื่อ:
- Real-time processing critical
- Multiple reactions to event
- High-volume data streams
- Asynchronous operations
- Event history important
- Scaling requirements high
- Loose coupling important

❌ ไม่ใช้เมื่อ:
- Real-time immediate response needed
- Simple request-response flow
- Low latency critical
- Event ordering critical
- Limited monitoring expertise
- Simple business logic
```

---

## 🔄 Event-Driven Patterns

### 1. Pub/Sub Pattern (Publisher-Subscriber)

```javascript
// Using EventEmitter (Node.js)
const EventEmitter = require("events");
const eventBus = new EventEmitter();

// Publisher (Order Service)
function createOrder(orderData) {
  const order = saveOrderToDb(orderData);

  // Publish event
  eventBus.emit("order.created", {
    orderId: order.id,
    userId: order.userId,
    total: order.total,
  });

  return order;
}

// Subscriber 1 (Email Service)
eventBus.on("order.created", (event) => {
  console.log(`Sending confirmation email for order ${event.orderId}`);
  sendEmail(event.userId, `Order ${event.orderId} created`);
});

// Subscriber 2 (Analytics Service)
eventBus.on("order.created", (event) => {
  console.log(`Recording analytics for order ${event.orderId}`);
  recordSale(event.total);
});

// Subscriber 3 (Inventory Service)
eventBus.on("order.created", (event) => {
  console.log(`Decreasing inventory for order ${event.orderId}`);
  updateInventory(event);
});
```

### 2. Message Queue Pattern (RabbitMQ / Kafka)

```javascript
// Using RabbitMQ

// Publisher
const amqp = require("amqplib");

async function publishEvent(event) {
  const connection = await amqp.connect("amqp://localhost");
  const channel = await connection.createChannel();

  const exchange = "orders";
  await channel.assertExchange(exchange, "topic", { durable: true });

  // Publish to exchange
  channel.publish(
    exchange,
    "order.created", // routing key
    Buffer.from(JSON.stringify(event))
  );

  console.log("Event published");
  await channel.close();
  await connection.close();
}

// Consumer
async function consumeEvents() {
  const connection = await amqp.connect("amqp://localhost");
  const channel = await connection.createChannel();

  const exchange = "orders";
  const queue = "email_service_queue";

  await channel.assertExchange(exchange, "topic", { durable: true });
  await channel.assertQueue(queue, { durable: true });

  // Bind queue to exchange with routing key
  await channel.bindQueue(queue, exchange, "order.*");

  // Consume messages
  channel.consume(queue, (msg) => {
    if (msg) {
      const event = JSON.parse(msg.content.toString());
      console.log(`Received: ${event.eventType}`);
      handleEvent(event);

      // Acknowledge message
      channel.ack(msg);
    }
  });

  console.log("Waiting for messages...");
}

function handleEvent(event) {
  switch (event.eventType) {
    case "order.created":
      console.log(`Sending email for order ${event.orderId}`);
      break;
    case "order.cancelled":
      console.log(`Sending cancellation email`);
      break;
  }
}

consumeEvents();
```

### 3. Apache Kafka Pattern (Stream Processing)

```javascript
// Using Kafka for high-volume events

const kafka = require("kafkajs");

// Producer
async function produceOrderEvents() {
  const producer = new kafka.Kafka({
    clientId: "order-service",
    brokers: ["kafka:9092"],
  }).producer();

  await producer.connect();

  const ordersToCreate = [
    { orderId: 1, userId: 10, total: 100 },
    { orderId: 2, userId: 11, total: 200 },
    { orderId: 3, userId: 12, total: 150 },
  ];

  for (const order of ordersToCreate) {
    await producer.send({
      topic: "orders",
      messages: [
        {
          key: String(order.orderId),
          value: JSON.stringify({
            eventType: "order.created",
            orderId: order.orderId,
            userId: order.userId,
            total: order.total,
            timestamp: new Date(),
          }),
        },
      ],
    });
  }

  await producer.disconnect();
}

// Consumer (Email Service)
async function consumeOrderEvents() {
  const consumer = new kafka.Kafka({
    clientId: "notification-service",
    brokers: ["kafka:9092"],
  }).consumer({ groupId: "notification-group" });

  await consumer.connect();
  await consumer.subscribe({ topic: "orders", fromBeginning: true });

  await consumer.run({
    eachMessage: async ({ topic, partition, message }) => {
      const event = JSON.parse(message.value.toString());

      if (event.eventType === "order.created") {
        console.log(`Sending confirmation email for order ${event.orderId}`);
        // Send email logic
      }
    },
  });
}

// Consumer (Analytics Service)
async function analyticsConsumer() {
  const consumer = new kafka.Kafka({
    clientId: "analytics-service",
    brokers: ["kafka:9092"],
  }).consumer({ groupId: "analytics-group" });

  await consumer.connect();
  await consumer.subscribe({ topic: "orders" });

  const totalRevenue = {};

  await consumer.run({
    eachMessage: async ({ message }) => {
      const event = JSON.parse(message.value.toString());

      const userId = event.userId;
      totalRevenue[userId] = (totalRevenue[userId] || 0) + event.total;

      console.log(
        `Total revenue from user ${userId}: $${totalRevenue[userId]}`
      );
    },
  });
}

produceOrderEvents();
consumeOrderEvents();
analyticsConsumer();
```

### 4. CQRS (Command Query Responsibility Segregation) Pattern

```javascript
// CQRS separates reads and writes

// Command Service (Write model)
class CreateOrderCommand {
  constructor(userId, items) {
    this.userId = userId;
    this.items = items;
  }
}

class CommandHandler {
  async handle(command) {
    if (command instanceof CreateOrderCommand) {
      return this.handleCreateOrder(command);
    }
  }

  async handleCreateOrder(command) {
    // Write to Write Model (database)
    const order = {
      id: generateId(),
      userId: command.userId,
      items: command.items,
      status: "pending",
    };

    await writeDb.orders.insert(order);

    // Publish event
    await eventBus.publish("order.created", order);

    return order;
  }
}

// Query Service (Read model)
class OrderQuery {
  async getOrder(orderId) {
    // Read from Read Model (optimized)
    return await readDb.orders.findById(orderId);
  }

  async getUserOrders(userId) {
    return await readDb.userOrders.findByUserId(userId);
  }
}

// Event Handler (Update read model)
async function handleOrderCreated(event) {
  // Update read model (denormalized)
  await readDb.orders.insert({
    id: event.orderId,
    userId: event.userId,
    items: event.items,
    status: "pending",
  });

  // Update user orders index
  await readDb.userOrders.add(event.userId, event.orderId);
}

// Usage
const handler = new CommandHandler();
const query = new OrderQuery();

// Write
const order = await handler.handle(new CreateOrderCommand(10, [...items]));

// Read (eventual consistency)
setTimeout(async () => {
  const result = await query.getOrder(order.id);
  console.log("Order from read model:", result);
}, 100);
```

---

## 💻 Code Examples

### Complete Event-Driven E-Commerce Example

```javascript
// ============================================
// EVENT BUS
// ============================================
const EventEmitter = require("events");

class EventBus {
  constructor() {
    this.emitter = new EventEmitter();
  }

  publish(eventType, data) {
    console.log(`📢 Event published: ${eventType}`, data);
    this.emitter.emit(eventType, {
      eventId: `evt_${Date.now()}`,
      eventType,
      timestamp: new Date(),
      data,
    });
  }

  subscribe(eventType, handler) {
    console.log(`📡 Subscribed to: ${eventType}`);
    this.emitter.on(eventType, handler);
  }
}

const eventBus = new EventBus();

// ============================================
// SERVICES
// ============================================

// Order Service (Producer)
class OrderService {
  constructor(eventBus, productService) {
    this.eventBus = eventBus;
    this.productService = productService;
    this.orders = [];
  }

  async createOrder(userId, items) {
    // Validate items
    for (const item of items) {
      const product = await this.productService.getProduct(item.productId);
      if (!product) {
        throw new Error(`Product ${item.productId} not found`);
      }
    }

    // Create order
    const order = {
      id: this.orders.length + 1,
      userId,
      items,
      status: "created",
      createdAt: new Date(),
    };

    this.orders.push(order);

    // 🚨 Publish event
    this.eventBus.publish("order.created", {
      orderId: order.id,
      userId: order.userId,
      items: order.items,
      total: this.calculateTotal(items),
    });

    return order;
  }

  calculateTotal(items) {
    return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
  }
}

// Email Service (Consumer 1)
class EmailService {
  constructor(eventBus) {
    this.eventBus = eventBus;

    // Subscribe to events
    this.eventBus.subscribe("order.created", (event) => {
      this.onOrderCreated(event);
    });

    this.eventBus.subscribe("payment.completed", (event) => {
      this.onPaymentCompleted(event);
    });
  }

  onOrderCreated(event) {
    console.log(
      `✉️ Email Service: Sending order confirmation for order ${event.data.orderId}`
    );
    // Send email logic
  }

  onPaymentCompleted(event) {
    console.log(
      `✉️ Email Service: Sending payment receipt for order ${event.data.orderId}`
    );
  }
}

// SMS Service (Consumer 2)
class SMSService {
  constructor(eventBus) {
    this.eventBus = eventBus;

    this.eventBus.subscribe("order.created", (event) => {
      this.onOrderCreated(event);
    });
  }

  onOrderCreated(event) {
    console.log(
      `📱 SMS Service: Sending SMS notification for order ${event.data.orderId}`
    );
  }
}

// Inventory Service (Consumer 3)
class InventoryService {
  constructor(eventBus, productService) {
    this.eventBus = eventBus;
    this.productService = productService;

    this.eventBus.subscribe("order.created", (event) => {
      this.onOrderCreated(event);
    });
  }

  async onOrderCreated(event) {
    console.log(
      `📦 Inventory Service: Reserving items for order ${event.data.orderId}`
    );

    for (const item of event.data.items) {
      // Decrease inventory
      await this.productService.decreaseStock(item.productId, item.quantity);
    }

    // Publish event
    this.eventBus.publish("inventory.reserved", {
      orderId: event.data.orderId,
      items: event.data.items,
    });
  }
}

// Payment Service (Consumer 4)
class PaymentService {
  constructor(eventBus) {
    this.eventBus = eventBus;

    this.eventBus.subscribe("inventory.reserved", (event) => {
      this.onInventoryReserved(event);
    });
  }

  onInventoryReserved(event) {
    console.log(
      `💳 Payment Service: Processing payment for order ${event.data.orderId}`
    );

    // Simulate payment
    setTimeout(() => {
      this.eventBus.publish("payment.completed", {
        orderId: event.data.orderId,
        amount: 250,
        status: "success",
      });
    }, 1000);
  }
}

// Analytics Service (Consumer 5)
class AnalyticsService {
  constructor(eventBus) {
    this.eventBus = eventBus;
    this.totalSales = 0;
    this.orderCount = 0;

    this.eventBus.subscribe("order.created", (event) => {
      this.onOrderCreated(event);
    });

    this.eventBus.subscribe("payment.completed", (event) => {
      this.onPaymentCompleted(event);
    });
  }

  onOrderCreated(event) {
    console.log(`📊 Analytics: Order created - ${event.data.orderId}`);
    this.orderCount++;
  }

  onPaymentCompleted(event) {
    this.totalSales += event.data.amount;
    console.log(
      `📊 Analytics: Total sales: $${this.totalSales}, Orders: ${this.orderCount}`
    );
  }
}

// ============================================
// PRODUCT SERVICE (Helper)
// ============================================
class ProductService {
  constructor() {
    this.products = [
      { id: 1, name: "Laptop", price: 999, stock: 10 },
      { id: 2, name: "Mouse", price: 29, stock: 100 },
      { id: 3, name: "Keyboard", price: 79, stock: 50 },
    ];
  }

  async getProduct(id) {
    return this.products.find((p) => p.id === id);
  }

  async decreaseStock(id, quantity) {
    const product = this.products.find((p) => p.id === id);
    if (product) {
      product.stock -= quantity;
    }
  }
}

// ============================================
// MAIN APPLICATION
// ============================================
async function main() {
  console.log("🚀 Starting Event-Driven E-Commerce System\n");

  // Initialize services
  const productService = new ProductService();
  const orderService = new OrderService(eventBus, productService);
  const emailService = new EmailService(eventBus);
  const smsService = new SMSService(eventBus);
  const inventoryService = new InventoryService(eventBus, productService);
  const paymentService = new PaymentService(eventBus);
  const analyticsService = new AnalyticsService(eventBus);

  console.log("=== System Initialized ===\n");

  // Create an order
  console.log("👤 User 1 creates an order...\n");

  const order = await orderService.createOrder(1, [
    { productId: 1, quantity: 1, price: 999 },
    { productId: 2, quantity: 2, price: 29 },
  ]);

  console.log("\n--- Order Created ---\n");

  // Wait for all events to be processed
  await new Promise((resolve) => setTimeout(resolve, 2000));

  console.log("\n✅ All events processed!");
}

main();

// Output:
// 🚀 Starting Event-Driven E-Commerce System
//
// === System Initialized ===
//
// 👤 User 1 creates an order...
//
// 📢 Event published: order.created
// ✉️ Email Service: Sending order confirmation for order 1
// 📱 SMS Service: Sending SMS notification for order 1
// 📦 Inventory Service: Reserving items for order 1
// 📊 Analytics: Order created - 1
// 📢 Event published: inventory.reserved
// 💳 Payment Service: Processing payment for order 1
// 📢 Event published: payment.completed
// ✉️ Email Service: Sending payment receipt for order 1
// 📊 Analytics: Total sales: $250, Orders: 1
//
// --- Order Created ---
//
// ✅ All events processed!
```

---

## 🌍 Real World Examples

### Example 1: Uber (Real-time Events)

```
Uber Event-Driven Flow:

1. Ride Requested
   Event: "ride.requested"
   Data: { userId, pickupLocation, dropoffLocation }

   ├→ Matching Service
   │  └→ Finds nearby drivers
   │     └→ Publishes "driver.matched"
   │
   ├→ Notification Service
   │  └→ Sends "Finding driver..." notification
   │
   └→ Analytics Service
      └→ Records ride request

2. Driver Matched
   Event: "driver.matched"

   ├→ Routing Service
   │  └→ Calculates route
   │
   ├→ Pricing Service
   │  └→ Calculates fare estimate
   │
   └→ Notification Service
      └→ Sends "Driver assigned" notification

3. Ride Started
   Event: "ride.started"

   ├→ Location Tracking Service
   │  └→ Sends real-time GPS updates
   │
   ├→ ETA Service
   │  └→ Updates ETA
   │
   └→ Payment Service
      └→ Starts tracking cost
```

### Example 2: Amazon (Order Processing)

```
Amazon Order Event Chain:

Order.Created
  ├→ Warehouse Service
  │  └→ "order.ready-for-shipment"
  │     ├→ Fulfillment Service
  │     │  └→ "shipment.created"
  │     │     ├→ Tracking Service
  │     │     └→ Notification Service ("Order shipped")
  │     └→ Analytics Service
  │
  ├→ Payment Service
  │  └→ "payment.processed"
  │     └→ Refund Service (on failure)
  │
  ├→ Inventory Service
  │  └→ Decreases stock
  │
  └→ Recommendation Service
     └→ Updates customer preferences

Return.Initiated
  ├→ Refund Service
  │  └→ Processes refund
  │
  ├→ Inventory Service
  │  └→ Adds stock back
  │
  └→ Notification Service
     └→ "Return approved"
```

### Example 3: Netflix (Streaming Events)

```
Netflix Event-Driven:

Content.Watched
  ├→ Progress Tracking Service
  │  └→ "content.progress-updated"
  │     └→ Recommendation Engine
  │        └→ Updates viewing habits
  │
  ├→ Analytics Service
  │  └→ "watch-time.recorded"
  │
  ├→ Notification Service
  │  └→ "watch-next-episode"
  │
  └→ Cache Service
     └→ Invalidates recommendations cache

Search.Performed
  ├→ Search Service
  │  └→ Returns results
  │
  ├→ Analytics Service
  │  └→ "search.logged"
  │
  └→ Recommendation Service
     └→ Updates search trends
```

---

## 🛡️ Best Practices

### 1. Event Design

```javascript
// ✅ GOOD: Clear, specific events
eventBus.publish("order.created", { orderId, userId, total });
eventBus.publish("order.cancelled", { orderId, reason });
eventBus.publish("payment.completed", { orderId, amount });

// ❌ BAD: Generic events
eventBus.publish("data-changed", { data }); // Too vague
eventBus.publish("something-happened", {}); // Unclear
```

### 2. Error Handling

```javascript
// ✅ GOOD: Graceful error handling
eventBus.subscribe("order.created", async (event) => {
  try {
    await processOrder(event);
  } catch (error) {
    console.error(`Failed to process order: ${error.message}`);
    // Publish error event
    eventBus.publish("order.processing-failed", {
      orderId: event.data.orderId,
      error: error.message,
    });
    // Optionally: send to dead-letter queue
  }
});

// ❌ BAD: No error handling
eventBus.subscribe("order.created", async (event) => {
  await processOrder(event); // What if it fails?
});
```

### 3. Idempotency

```javascript
// ✅ GOOD: Idempotent event handling
async function handleOrderCreated(event) {
  // Check if already processed
  const processed = await db.eventLog.findOne({
    eventId: event.eventId,
  });

  if (processed) {
    return; // Already handled
  }

  // Process event
  await processOrder(event);

  // Mark as processed
  await db.eventLog.insert({
    eventId: event.eventId,
    timestamp: new Date(),
  });
}

// ❌ BAD: Not idempotent (duplicate processing)
async function handleOrderCreated(event) {
  await processOrder(event); // Might be called twice!
}
```

### 4. Event Ordering

```javascript
// ✅ GOOD: Maintain order with key
kafka.producer.send({
  topic: "orders",
  messages: [
    {
      key: String(order.userId), // Same user → same partition → same order
      value: JSON.stringify(event),
    },
  ],
});

// Consumer gets events in order
async function consume() {
  await consumer.run({
    eachMessage: async ({ message }) => {
      const event = JSON.parse(message.value);
      // Events from same user are ordered
    },
  });
}
```

### 5. Event Versioning

```javascript
// ✅ GOOD: Version events
{
  "eventType": "order.created",
  "version": "2.0", // New version
  "data": {
    "orderId": 1,
    "userId": 10,
    "items": [...],
    "total": 250,
    "newField": "value" // Added in v2
  }
}

// Handle multiple versions
async function handleOrderCreated(event) {
  if (event.version === "1.0") {
    // Old format
    const orderId = event.data.orderId;
  } else if (event.version === "2.0") {
    // New format with more fields
    const { orderId, newField } = event.data;
  }
}
```

### 6. Monitoring Events

```javascript
// ✅ GOOD: Monitor event flow
let eventMetrics = {};

eventBus.subscribe("*", (event) => {
  const type = event.eventType;
  eventMetrics[type] = (eventMetrics[type] || 0) + 1;

  console.log(`Event: ${type}, Total: ${eventMetrics[type]}`);

  // Send to monitoring service
  monitoringService.recordEvent(type);
});

// Expose metrics
app.get("/metrics", (req, res) => {
  res.json({
    totalEvents: Object.values(eventMetrics).reduce((a, b) => a + b, 0),
    byType: eventMetrics,
  });
});
```

---

## 📊 Event-Driven vs Other Patterns

| Aspect               | Event-Driven | Layered | Microservices |
| -------------------- | ------------ | ------- | ------------- |
| **Coupling**         | Loose        | Tight   | Medium        |
| **Real-time**        | Excellent    | Poor    | Good          |
| **Scaling**          | High         | Medium  | Very High     |
| **Complexity**       | High         | Low     | Very High     |
| **Testing**          | Moderate     | Easy    | Hard          |
| **Event History**    | ✓            | ✗       | Optional      |
| **Async Processing** | ✓            | Limited | ✓             |
| **Debugging**        | Hard         | Easy    | Hard          |

---

## ✅ ตรวจสอบความเข้าใจ

**คำถามตัวเอง:**

1. ✓ Event-Driven vs Request/Response ต่างกันอย่างไร?
2. ✓ Event broker ทำไมต้อง?
3. ✓ Pub/Sub pattern คืออะไร?
4. ✓ Eventual consistency ทำไมต้องในระบบ event-driven?
5. ✓ CQRS pattern ใช้ทำไม?
6. ✓ Idempotency ทำไมสำคัญ?
7. ✓ Event ordering ควรรักษาอย่างไร?

---

## 📚 สรุป

### Key Takeaways

```
✅ Event-Driven = Loose coupling, asynchronous
✅ Good for: Real-time, high-volume, scalable systems
✅ Pub/Sub: One-to-many communication
✅ Message Queues: Reliable, ordered delivery
✅ CQRS: Separate reads and writes
✅ Need: Sophisticated monitoring, good design
❌ Cons: Complex, hard to debug, eventual consistency
```

### เมื่อไดควรเลือก Event-Driven

```
✅ USE IF:
- Real-time processing critical
- Multiple reactions per event
- High-volume data streams
- Loose coupling important
- Event history valuable
- Asynchronous operations

❌ DON'T USE IF:
- Real-time immediate response needed
- Simple request-response
- Low latency absolutely critical
- Eventual consistency not acceptable
- Simple business logic
- Limited monitoring expertise
```

---
