THIS EXPLANATION
THE ROOM
CDA·43 Computing, Data & AI 6 MIN · 8 STATIONS

Commands and events

A Socratic walk-through of commands and events — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

Why does naming a message in the past tense change the shape of the whole system?

Two messages cross the same broker, carry the same fields, and are serialised identically. One is called SendWelcomeEmail. The other is called UserRegistered.

A reasonable first reaction is that this is a naming convention — pleasant, tidy, and of no structural consequence. Yet architects treat the distinction as load-bearing, and systems built on one convention end up looking nothing like systems built on the other. If the bytes are the same, the difference must live somewhere other than the message. Working out where turns out to be the whole subject.

b

Reasoning it through

REASONING #

Start with who is entitled to decide. SendWelcomeEmail says the sender has already decided what should happen; the receiver's job is to carry it out. UserRegistered says the sender has reported something that occurred, and what to do about it is somebody else's judgement. The tense is a claim about which party holds the decision.

Follow that to its consequence for knowledge. To send a command, you must know a recipient exists, and something about what it does — otherwise you could not have chosen it. To publish an event, you need know nothing at all about who is listening; the fact is true whether anyone reads it or not. So the sender of a command depends on the receiver, while the receiver of an event depends on the publisher. The tense reverses the direction of the dependency arrow, and that is not a naming convention.

Now ask about failure, which is where the difference becomes operationally sharp. A command can be refused: the amount is invalid, the account is frozen, the caller is not permitted. It is a request whose outcome is genuinely in doubt, so the sender usually wants an answer. An event cannot be refused — the user did register — and a subscriber that dislikes it has no standing to reject it. It can only ignore it, or take a compensating action afterwards. Nothing in the protocol changed; what changed is that there is no longer anything meaningful to say back.

And cardinality follows from that. A command with two handlers is almost always a bug: two systems each debiting the account, each believing they were asked. An event with two subscribers is entirely normal, and adding a third later requires no change to the publisher whatsoever. This is the property that actually gets systems built on events — extension without modification of the thing that emits.

So consider what happens to a design under each convention. Command-shaped: an order service that must know about the email service, the warehouse, the loyalty scheme, and the fraud checker, and that must be edited whenever a new consequence of ordering is invented. Event-shaped: an order service that announces OrderPlaced and knows none of them. The business logic is identical; the map of who-knows-whom is completely different, and it is that map, rather than the code, which decides how expensive the next change is.

There is a failure mode worth naming, because it is the common one. A message called OrderPlaced that has exactly one subscriber, which must handle it, and whose author will be paged if it does not, is a command wearing a past-tense costume. The publisher does depend on that subscriber — the dependency has simply been removed from the code and left in the operational reality, where nothing checks it. The tense is honest only if you would genuinely be untroubled by nobody listening.

The reverse mistake exists too, and it is less discussed: forcing an event shape onto an interaction that needs an answer. If the caller must know whether the payment succeeded before it can continue, a fire-and-forget announcement makes the caller reconstruct a reply out of correlation identifiers and timeouts. That is a real design — it is how sagas work — but it is a considerable cost to accept in exchange for a decoupling nobody needed.

One caveat on terminology. The distinction is a matter of intent, and intent is not carried in the wire format — brokers do not enforce it, and the same infrastructure serves both. The vocabulary is also not perfectly standardised: "event notification" that carries only an identifier, and "event-carried state transfer" that carries the full changed state, are both called events while implying quite different coupling to the publisher's data model.

c

The analogy

THE ANALOGY #
THE FIGURE

Think of the difference between handing someone a work order and posting a notice on the wall. The work order names a person, expects them to do it, and can come back marked refused. The notice states what happened; anyone who cares reads it and acts on their own initiative, nobody signs for it, and you can pin it up whether or not there is anyone in the corridor.

WHERE IT BREAKS DOWN

a notice on a wall is passive and may simply go unread with no consequence, whereas a published event usually is relied upon by somebody — so the freedom from knowing your readers is real in the code and only partly real in operation, where a missing subscriber still breaks the business.

d

Clarifying the model

THE MODEL #

Three refinements.

First, both are messages, and both may travel over exactly the same broker with the same delivery guarantees. Nothing technical distinguishes them; the distinction is a discipline in naming and in who is allowed to depend on whom.

Second, a command is not the same as a synchronous call. Commands are routinely asynchronous — queued, retried, handled minutes later. What defines them is a named recipient, an expectation of action, and the possibility of refusal, not the transport or the timing.

Third, past tense is a test rather than a rule. The useful question is not "did I conjugate the verb correctly" but "if nobody subscribes to this, is the publisher still correct?" If yes, it is genuinely an event. If no, it is a command, and calling it an event only hides the dependency from the diagram.

e

A picture of it

THE PICTURE #
Commands and events
Commands and events The horizontal axis asks whether the receiver could legitimately say no; the vertical asks how many parties are entitled to act. Healthy designs sit in the bottom-left and top-right: instructions with one accountable handler, and facts anyone may subscribe to. The top-left is the failure discussed above -- something refusable being broadcast, which means several parties each half-own a decision -- and the bottom-right is a settled fact with a single reader, harmless but a sign the publisher has been shaped around one consumer. {"generator":"[email protected]","source":"../Socrates/.diagram-cache/_src/commands-and-events.md","sourceIndex":1,"sourceLine":4,"sourceHash":"228a83b2ec8eed5d9a10be80790f4b7f866a140216c2bd2703b34dad00c90939","diagramType":"quadrantChart","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":720,"height":621},"qa":{"passed":true,"findings":[]}} Published facts Q1 Disguised commands Q2 Direct instructions Q3 Private facts Q4 Balance snapshot Please recalculate Order was shipped Charge the card Refusable Settled One handler Many listeners Messages placed by intent

How to readThe horizontal axis asks whether the receiver could legitimately say no; the vertical asks how many parties are entitled to act. Healthy designs sit in the bottom-left and top-right: instructions with one accountable handler, and facts anyone may subscribe to. The top-left is the failure discussed above — something refusable being broadcast, which means several parties each half-own a decision — and the bottom-right is a settled fact with a single reader, harmless but a sign the publisher has been shaped around one consumer.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

Naming a message in the past tense is a declaration that the sender has given up the decision about what happens next — and that is what reverses the dependency, removes the possibility of refusal, and makes the number of listeners the publisher's business no longer. The system's shape changes because the tense changes who must know about whom, which is the only thing an architecture diagram is really recording.

g

Where to go next

ONWARD #
  • Event notification versus event-carried state transfer, and the coupling each creates to the publisher's data.
  • Sagas: recovering an answer when the interaction genuinely needed one.
  • How to name events so the publisher's own vocabulary, not the subscriber's, decides the wording.
h

Key terms

TERMS #
TermWhat it means
Commanda message instructing a named recipient to do something, which may be refused.
Eventa message reporting something that has already happened, addressed to nobody in particular and not refusable.
Compensating actionan operation that offsets the effects of something already done, used where rejection is impossible.
Event-carried state transferpublishing the full changed state with an event so subscribers need not call back for it.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4