m@ksim.pro
Back to all posts
IT 3 min read

Event-driven architecture: when it helps and when it creates noise

A practical look at event-driven design - what problems it solves, where it adds complexity without benefit, and how to decide whether you need it.

Over the past year I have had this conversation several times: an engineering team proposes switching to an event-driven architecture, the proposal sounds convincing, and the business signs off without fully understanding what it is buying. Sometimes that turns out well. Often it does not.

The pattern itself is solid. The problem is that it is applied too broadly, to situations where a simpler model would work better and be easier to operate.

What the pattern actually does

In event-driven architecture, components do not call each other directly. Instead, one component emits an event - "order placed", "payment received", "document uploaded" - and any other component that cares about that event reacts to it independently.

The coupling is loose. A producer does not know who is listening. A consumer does not know who produced. You can add new consumers without touching existing code.

This is genuinely useful in specific situations.

Where it earns its cost

The pattern makes sense when:

  • Several independent systems need to react to the same business event. An order placement might trigger inventory, billing, notification, and analytics in parallel. Calling each service sequentially is fragile and slow.
  • Peak loads are uneven. A queue between producer and consumer lets you absorb spikes without dropping requests.
  • Audit and replay matter. An event log gives you a complete history of what happened and when. You can replay it to rebuild state or feed a new consumer with historical data.
  • Teams are independent. If the billing team and the fulfilment team deploy on different schedules, tight coupling creates coordination overhead that compounds over time.

Where it adds complexity without a matching payoff

The pattern is often proposed in smaller contexts where it does not fit:

  • A straightforward CRUD application with one or two consumers does not need a message broker. A direct call or a database trigger is easier to understand and debug.
  • If the business cannot tolerate eventual consistency - for example, a payment must be confirmed before any further action - then asynchronous events require careful compensating logic that often becomes harder than the original synchronous flow.
  • Small teams often underestimate the operational cost: managing broker infrastructure, monitoring consumer lag, handling poison messages, and tracing requests across async boundaries requires tooling and discipline.

What to verify before choosing the pattern

I ask these questions before recommending event-driven design:

  1. How many independent consumers need to react to the same event today? How many in a year?
  2. Does the business process allow for a delay between event and reaction, or must it be synchronous?
  3. Who will operate the broker and how will incidents be diagnosed?
  4. Does the team have experience with idempotency and at-least-once delivery?
  5. What does the rollback story look like when something goes wrong mid-flow?

If the answers are "one consumer, zero tolerance for delay, and no one has run Kafka before" - the synchronous option is almost certainly the right starting point.

A practical starting point

If you are evaluating this pattern, start with the business process first, not the technology. Map the events that already exist in the domain - what happens, what needs to react, and what the latency tolerance is. Then check whether the team can operate what you are proposing.

The architecture should reduce operational friction over time, not increase it immediately with the promise of future flexibility.

Back to all posts
Contact

If this resonated, write to me. I reply personally.

WhatsApp