Skip to main content

Event-Driven Architecture — Async Decoupling via Events

Producers emit events; consumers react asynchronously — zero direct coupling between them.

When to use

  • Fan-out: one event needs to trigger multiple independent consumers
  • Audit trail or replay required
  • Temporal decoupling needed (producer/consumer scale independently)

Tradeoffs

  • End-to-end flow tracing requires distributed tracing (harder to debug)
  • Eventual consistency — consumers may lag
type OrderPlaced struct {
OrderID string
CustomerID string
Total float64
}

func publishOrder(ch chan<- OrderPlaced, evt OrderPlaced) {
ch <- evt
}

func consumeOrders(ch <-chan OrderPlaced) {
for evt := range ch {
fmt.Printf("handling order %s\n", evt.OrderID)
}
}

Gotcha: Events are facts, not commands. Name them in past tense: OrderPlaced, not ProcessOrder.