skip to content

What is the difference between an event and a command in an event-driven system, and how does that distinction shape how you name and publish messages to Kafka topics?

level: juniorimportance: must knowfreq 78%

answer

  1. Event = past tense fact; command = imperative intent
  2. Event: publisher doesn't know consumers
  3. Command: sender knows receiver (coupling)
  4. OrderPlaced vs PlaceOrder
  5. Kafka topic = natural event bus; commands need keyed/dedicated topic

basics

~20 s

An event states something that already happened (past tense, e.g. OrderPlaced) and has no specific intended recipient. A command tells one service to do something (imperative, e.g. PlaceOrder) and expects an action. Events go to topics for any consumer; commands target one handler.

solid answer

~50 s

An event is an immutable fact about something that already occurred — named in the past tense like OrderPlaced or PaymentCaptured. The publisher does not know or care who consumes it; any number of consumers can subscribe to the topic. A command is an intent/instruction directed at a specific service to perform an action — named imperatively like ShipOrder — and the sender expects it to be handled (often exactly once). In Kafka, both can be serialized to topics, but events are the natural fit: producers broadcast facts to a topic, consumers in independent consumer groups each read them. Commands over Kafka usually use a dedicated topic keyed so one logical handler processes them, and they imply a sender-knows-receiver coupling. Mixing them up leads to producers encoding behavior expectations into 'events', which couples services. The naming convention (past-tense vs imperative) is the simplest discipline that keeps the distinction visible.

go deeper

for a junior

Recall the past-tense vs imperative naming and that events have unknown consumers while commands target one.

for a middle

Explain the coupling-direction inversion and how each maps onto Kafka topics/keys.

for a senior

Reason about request/reply, once-only command handling, and when a direct RPC beats a command topic.

for a principal

Set org-wide conventions for naming, topic taxonomy (events vs commands), and review gates that keep the semantics honest at scale.

## First principles A **message** is any piece of data one service sends to another. Event-driven design distinguishes two kinds of message by *intent*: - **Event** — a statement that **something already happened**. It is a *fact*, it is immutable, and it is named in the **past tense**: `OrderPlaced`, `PaymentCaptured`, `InventoryReserved`. The publisher emits it and **does not know who, if anyone, will consume it**. Zero, one, or many consumers may react. The publisher has *no expectation* about what happens next. - **Command** — an **instruction to do something**, named in the **imperative**: `PlaceOrder`, `ShipOrder`, `ReserveInventory`. It is directed at a **specific** recipient, the sender **expects** it to be acted on, and it can be **rejected** (the action might not be valid). It typically should be handled **once**. The mnemonic: an event says *'this is true'*; a command says *'please make this true'*. ## Why it matters for coupling The direction of knowledge differs: - With a **command**, the **sender knows the receiver** ('I want *the shipping service* to ship this'). That is a form of coupling — the sender depends on the existence of a handler. - With an **event**, the **publisher knows nothing about subscribers**. Consumers depend on the event, not the other way round. This *inverts the dependency* and is what makes event-driven systems loosely coupled and extensible: you can add a new consumer (analytics, fraud, email) without touching the producer. ## How this maps onto Kafka Kafka is a **partitioned, durable log**. A producer appends records to a **topic**; **consumer groups** each maintain their own offset and read independently. This is a natural **event** transport: one topic of `OrderPlaced` events can be consumed by the billing group, the analytics group, and the email group at once, each at its own pace. Commands can also be sent over Kafka, but with a different shape: - Use a **dedicated command topic** (e.g. `shipping.commands`). - **Key** the record so a single logical consumer/partition handles each command, preserving per-entity ordering. - Accept that the sender now depends on that handler existing. ## Edge cases & pitfalls - **'Eventy commands'**: emitting `OrderPlaced` but secretly expecting *exactly one* service to ship the order, and breaking if a second consumer appears — that is a command wearing an event's name. Keep semantics honest. - **Request/reply over Kafka**: a command often wants a result. You implement reply with a correlation id and a reply topic, but this reintroduces synchronous-style coupling — sometimes a direct REST/gRPC call is simpler. - **Naming discipline** is the cheapest enforcement: reviewers can reject a past-tense name on a command topic or an imperative name on a domain-event topic. - Both events and commands should carry a **schema** (Avro/Protobuf/JSON Schema in a registry) so consumers/handlers can evolve safely.

  • Can you send a command over Kafka, and what changes versus an event?
    Yes — use a dedicated command topic, key records so one logical handler processes each, and accept that the sender now couples to that handler. Unlike events, you usually want once-only handling and sometimes a reply via correlation id + reply topic.
  • How does the event-vs-command distinction affect coupling direction?
    With commands the sender depends on the receiver. With events the dependency inverts — consumers depend on the event, the publisher knows nothing about subscribers — which is what enables adding consumers without changing producers.

saying these in an interview costs you the question

  • Saying events and commands are the same thing with different names
  • Claiming the event publisher chooses which consumer handles the event
  • Naming a command in past tense or an event in imperative form
  • Believing Kafka can only carry events, never commands

context