Command vs Event: It’s About Where the Logic Lives

In most cases, the decision between sync and async is straightforward.

If you must know the result immediately (e.g. payment authorization, OTP), you go synchronous.

Otherwise, you go async.

The real question is:

When using async, should we send a Command or publish an Event?

1. Async Decision: Command vs. Event

Once we choose async, we usually end up with two options:

  • Send a Command

  • Publish an Event

At a glance, they look very similar — both go through queues.

But in practice, they lead to very different systems.

A simple comparison

** 2. The Real Problem in Practice**

In real systems, this decision is rarely clean.

You often see a lot of async commands already in place, and later a push to “move to events” for better decoupling. But after the change, things don’t necessarily get simpler — just different.

Logic doesn’t disappear — it moves

What do you feel

Command:

  • Easy to follow — everything is in one place

  • Low coordination cost

  • But tends to leak logic and create coupling

Event:

  • Decoupled and extensible

  • But spreads logic across services

  • And increases coordination and debugging cost

In short:

  • Command keeps things visible but coupled

  • Event decouples but spreads the logic

3. What should drive the decision?

The real decision is not “Command or Event” in isolation.

It is a trade-off between:

  • keeping the logic centralized, at the cost of tighter coupling

  • decoupling services, at the cost of distributing the logic

So the useful question is:

What matters more in this case: visibility or decoupling?

A few factors usually drive that decision:

  • Flow visibility — Do we need one place to understand and debug the business flow?

  • Expected growth — Is this likely to attract more downstream reactions over time?

  • Coordination cost — Can the teams afford the extra schema, tracing, and ownership overhead?

  • Cost of coupling — Is the downstream a simple utility, or a separate domain we don’t want to bind to?

In practice:

  • Choose Command when keeping the flow visible and local matters more

  • Choose Event when reducing coupling and enabling future extensibility matters more