Learning · Event-driven & Kafka

Events, commands, and messages

Facts vs instructions — how to name and shape messages so Kafka topics stay trustworthy contracts.

Not every message on a bus is an event. Mixing facts, commands, and private transport on the same topics is how teams lose trust in the log.

Events are facts

An event records something that already happened in a domain: PaymentCaptured, RefundIssued, SettlementFileReceived.

Good events:

  • use past tense domain language
  • carry enough data for consumers to react without calling back for the obvious fields
  • are owned by the service that enforced the invariant
  • stay stable as a contract — additive evolution, not silent renames

Consumers may build projections, trigger workflows, or notify people. They do not get to redefine what the event meant.

Commands are instructions

A command asks someone to do work: CapturePayment, IssueRefund. It has an intended recipient and usually expects an outcome.

Commands can travel over Kafka, but treat them as directed work, not public history. Prefer clear ownership (one consumer group that executes the command) and explicit success/failure handling. Do not pretend a command is a domain event just because it is on a topic.

Messages that should stay private

Internal queue payloads, retry wrappers, and framework envelopes are implementation details. Keep them off public domain topics. Public topics are contracts; private queues are transport.

Naming and payload discipline

  • Name topics and event types after the domain, not the producer’s class name
  • Prefer explicit event type fields over guessing from topic alone
  • Include correlation / causation IDs so traces survive async hops
  • Include a stable business key (payment id, account id) for partitioning and idempotency
  • Avoid dumping entire aggregated graphs “just in case” — publish what consumers need, version when they need more

If you cannot say whether a payload is a fact or an instruction, stop and redesign before adding another consumer.

← Event-driven & Kafka