The Architecture Reference

Ed foundations · Guide · Start here

Thinking in Events

Events versus commands versus messages — and why a durable, replayable event is a different medium that decouples who owns data from who consumes it.

Ed foundations Start here ⏱ 5 min read Complete

🧭 Analogy

A command is a phone call: you dial a specific person and wait for them to act. A message is a letter dropped in one mailbox and removed when read. An event is an entry in the public ledger of record — once written, it stays there forever, and anyone, now or years from now, can read the same page and reach the same conclusion.

Marshall McLuhan said “the medium is the message.” Adam Bellemare opens Building Event-Driven Microservices with that line because the event has been transformed by modern technology: events can now be persisted indefinitely at large scale and re-read by any service as often as needed. That single change — durability plus replay — turns events from throwaway notifications into the single source of truth for an organization.

Events vs. commands vs. messages

These three are routinely confused, and conflating them quietly re-introduces the coupling event-driven design is meant to remove.

  • Command — an imperative instruction aimed at a specific handler: “charge this card.” It expects something to happen and often a response. It is point-to-point and couples the sender to the receiver.
  • Event — a declarative statement of fact about something that already happened: “payment was captured.” It is addressed to no one in particular; producers do not know who consumes it.
  • Message — a transport-level envelope. In a classic message broker each message lands in a queue, is consumed once, and is deleted. That makes it impossible to communicate state to multiple consumers.

The key insight

Events are not destroyed on consumption. An event broker maintains a single immutable, replayable ledger; each consumer tracks its own offset. This is why a stream can serve as the single source of truth while a queue cannot.

The shape of an event

Events use a key/value structure. Bellemare distinguishes three kinds:

  • Unkeyed event — a singular statement of fact (a user opens a book).
  • Entity event — keyed on a unique ID, describing an entity’s state at a point in time. Only the latest event per key is needed for current state.
  • Keyed event — has a key but is not an entity; used mainly for partitioning and data locality.

Applying entity events in order and upserting each into a key/value table — latest-per-key wins — materializes state. The reverse, emitting a stream from table changes, is equally valid. This table-stream duality lets any consumer build its own local state store from a stream alone, with no direct coupling to the producer.

graph LR
S["Stream of entity events<br/>k1=v1, k2=v2, k1=v3"] -->|"upsert latest per key"| T["Table<br/>k1=v3, k2=v2"]
T -->|"emit on change"| S2["Stream"]
S2 -.->|"same data, two forms"| S
graph TD
P["Producer<br/>(single writer)"] -->|"appends facts"| L["Event stream<br/>(immutable log)"]
L -->|"offset A"| C1["Consumer A<br/>materializes its own view"]
L -->|"offset B"| C2["Consumer B<br/>aggregates"]
L -->|"offset C"| C3["Consumer C<br/>replays history"]

Why the medium reshapes the organization

Bellemare names three communication structures: the business structure (teams), the implementation structure (a service and its database), and the frequently-missing data communication structure (how data actually moves between implementations). Invoking Conway’s Law, he shows that when the data structure is weak, the implementation structure is forced to do double duty — services absorb extra scope just to source data they need, blurring boundaries and breeding distributed monoliths.

Publishing all shareable data to event streams inverts this. Producers are limited to producing well-defined facts; consumers each take their own copy and do their own modeling and querying. Core domain data becomes accessible independent of any one implementation — which is what makes teams and services free to change. See coupling and asynchrony trade-offs for the costs of this freedom.

Don't use events as semaphores

An event that merely signals “something happened” without carrying the result creates two sources of truth: consumers must call back to find out what actually changed. Tell the truth, the whole truth, and nothing but the truth — the event should carry enough that a consumer never needs another data source.

See also

When to use it — and when not

✅ Reach for it when

  • Many independent consumers need the same business facts without coupling to the producer
  • You want the history of what happened to be durable, replayable, and the single source of truth
  • Teams and services must evolve independently, on their own schedules
  • Consumers need to build and re-build their own local read models from a stream alone
  • The data communication structure is weak and services keep absorbing scope just to source data

⛔ Think twice when

  • A single caller needs an immediate, synchronous answer (authentication, a price quote)
  • The organization is too small to pay the broker, CMS, and tooling overhead (the microservice tax)
  • Strong read-after-write consistency is required inside one transaction boundary
  • The interaction is purely point-to-point with no current or future downstream consumers
  • You only need at-most-once fire-and-forget signalling that no one must replay

Check your understanding

Score: 0 / 5

1. What is the defining difference between an event broker and a message broker?

Because events are not destroyed on consumption, any number of consumers can read the same stream at their own pace — that is what makes the stream a single source of truth.

2. An 'entity event' is best described as…

Entity events are keyed on a unique ID; applying them in order and upserting the latest per key materializes current state — the basis of table-stream duality.

3. Why does Bellemare emphasize the often-missing 'data communication structure'?

Per Conway's Law, weak data communication makes services absorb extra responsibility just to source data, blurring boundaries and tightening coupling.

4. A command differs from an event because a command…

Commands say 'do this' (imperative, often expecting a response); events say 'this happened' (declarative fact). Conflating them re-introduces coupling.

5. What distinguishes a microservice topology from a business topology?

Topology has two senses: the per-service ingest/transform/materialize/emit logic, and the larger composition of many services and streams that together deliver business value.

Comments

Sign in with GitHub to join the discussion.