# Back to Code | Ep 13: Event-Driven Architecture — Kafka and the Async World

> Source: <https://dev.to/turacthethinker/back-to-code-ep-13-event-driven-architecture-kafka-and-the-async-world-1f9p>
> Published: 2026-05-26 11:38:27+00:00

The 15-week technical battle of LogiFlow — a company waking up from the illusion created by artificial intelligence and returning to real engineering.

When the "Invoice" service crashed, the "Routing" service also went down — because AI had connected them with synchronous HTTP (REST). **Cascade Failure.**

It was 2 AM when the pager went off. The invoice service had run out of memory — a memory leak in a PDF generation library. Within seconds, the routing service started timing out. Then the tracking service. Then the customer portal. One service's failure had cascaded through the entire system like dominoes.

"Why does the routing service care if invoicing is down?" Defne asked, already knowing the answer.

"Because AI made routing call invoicing synchronously after every route calculation," Emre admitted.

```
// Routing service (Producer)
await kafka.send({
  topic: 'routing.events',
  messages: [{
    key: truckId,
    value: JSON.stringify({
      type: 'RouteCalculated',
      truckId,
      eta,
      timestamp: Date.now()
    })
  }]
});

// Invoice service (Consumer) — Runs independently
consumer.run({
  eachMessage: async ({ message }) => {
    const event = JSON.parse(message.value);
    if (event.type === 'RouteCalculated') {
      await generateInvoice(event);
    }
  }
});
```

**Microservices should talk through Domain Events, not HTTP.**

When the invoice service goes down now, the routing service doesn't notice. The events queue up in Kafka. When invoicing recovers, it processes the backlog. No cascade. No domino effect. No 2 AM pages.

| Synchronous (HTTP) | Asynchronous (Events) |
|---|---|
| Caller waits for response | Fire and forget |
| Failure cascades | Failure is isolated |
| Tight coupling | Loose coupling |
| Easy to reason about | Requires event schema design |
| Simple for 2 services | Essential for 10+ services |

**1. Loose Coupling:** Services should not wait for each other.

**2. Domain Events:** 'RouteCalculated', 'InvoiceGenerated' — communicate through events.

**3. Dead Letter Queue:** Failed messages should not be lost — they should wait in a separate queue for investigation and replay.

*This is Episode 13 of the "Back to Code" series. Next up: Episode 14 — Technical Debt Credit Score.*

*Series: back.to.code · 2026*
