Event-Driven Architecture Without Event Sourcing Complexity
Most teams hear "event-driven" and picture Kafka clusters, event sourcing, CQRS, and a three-month ramp-up. That picture costs more than it delivers for most projects.
I built Srabutan's order pipeline on pure event-driven patterns without a single event store. No event sourcing. No Kafka. Just RabbitMQ, a few strategic exchanges, and the outbox pattern. Two years later, I have not regretted that choice once.
Two Families, One Confusion
Event-driven architecture splits into two families that people keep confusing: event notification (something happened, go check it out) and event-carried state transfer (something happened, here is all the data).
Event sourcing belongs to neither family. It is a persistence pattern where the event log serves as the source of truth. You can build event-driven systems without it.
The Patterns I Use Instead
Outbox Pattern + Message Broker. You write to your database and publish an event in the same transaction. A separate worker reads the outbox table and publishes to the broker. One atomic transaction. No distributed coordination.
Change Data Capture. Sometimes you cannot modify the source system to emit events. CDC captures database changes at the WAL level and turns them into event streams.
Plain Pub/Sub With Competing Consumers. Not every event needs a stream. Work distribution often needs nothing more than a fanout exchange for broadcasting or a direct exchange for load balancing.
The Real Cost of Over-Engineering
A team I consulted for spent two months setting up Kafka, a schema registry, Avro serialization, and event sourcing — all to power a notification service that sent three emails per day.
Start with the outbox pattern and a message broker. Add event sourcing when the business demands it, not when a conference talk convinces you it is mandatory.
$ /related
CQRS in Practice: When Textbook Patterns Meet Real Constraints
CQRS looks elegant in architecture diagrams. In production, it introduces complexity you didn't plan for. Here's what I learned applying it under real constraints.
React Server Components Made Me Rethink Client-Side
RSC doesn't just move rendering to the server. It destroys the 'client vs. server' mental model and replaces it with something sharper.
Building a Reconciliation Engine for Currency Mismatch
Multi-currency transactions break naive reconciliation. I built an engine with threshold-based matching that handles FX rate gaps and rounding without drowning in false positives.