Events vs Messages
Facts to remember vs commands to act
An event is a durable fact about what happened, addressed to interest groups; a message is a transient command aimed at a specific consumer. Choosing the wrong one shapes your entire architecture.
What you will learn
- Distinguish events (facts) from messages (commands)
- Explain why events enable replay and multiple consumers
- Pick event vs message for a given system
What is this?
Events are records of what happened (e.g. 'order shipped') — immutable facts stored in a log, consumable by any interested party, replayable forever. Messages are imperatives aimed at one consumer ('please ship order 42') and are typically transient. Event-driven systems build on events; request/command systems build on messages; many real platforms use both.
Why do you need it?
- Events decouple teams: a fact can be replayed or re-read without the original publisher.
- Messages tightly bind producer and consumer semantics, which is fine for commands, poor for facts.
- Event sourcing and streaming analytics both require durable, replayable events.
- Choosing the wrong paradigm produces ugly hacks (exposing command queues as 'events').
Mental model
A town bulletin board vs a phone call
Events vs messages
The bulletin board (event log) posts facts anyone can read later, even years on. The phone call (message) is a direct instruction to one person right now — if they miss it, it's gone.
How it works
- An event carries a subject, a type, a timestamp and a payload ('user.registered @ 2026-09-22 10:00').
- Events are written to a partitioned log and retained (with retention policies).
- Multiple consumers read the same event — analytics, search index, ML, notifications — with their own offsets.
- A message carries a destination and semantics: 'do this' — consumed once, often acknowledged, then gone.
- Some brokers blend both: Kafka topics for events, and queue-like patterns/retries for commands.
Event (log) vs message (queue) semantics.
In production
- An 'order.placed' event drives inventory, billing, notifications and analytics — each subscribing independently.
- A 'redeem voucher' message commands one service to act once; retries and ack protocols manage delivery.
- Event sourcing stores the full command history ('permissions.changed', 'profile.updated') for audit and replay.
Best practices
- Name events in past tense and carry their own data (self-contained events).
- Keep command semantics (do this, once) out of the event log.
- Version event schemas so old readers keep working.
- Give events a stable schema and clear producer metadata for observability.
Common mistakes
- Modelling commands as events, then wondering why replay produces wrong side effects ('do X' re-executes X).
- Consuming an event to delete it instead of retaining for other/analytics consumers.
- Embedding the expected recipient in the event, coupling producers to consumers.
Common issues
Replaying a topic duplicates downstream processingConsumers treat the replayed events as commands instead of idempotent facts
Make consumers idempotent (keyed dedupe) or move commands out of the event topic.
An event consumer can't read events produced before a schema changeSchema evolution broke backward compatibility
Use a schema registry with compatible evolution, and keep readers tolerant of unknowns.
Debugging tips
- If replaying a topic causes duplicate side effects, so your events are actually commands.
- Check whether events carry a schema and producer id — half of event bugs are malformed payloads.
- Cross-version events (old + new schema) break readers — check schema registry before the topic.
Interview checkpoint
Quick quiz
Which should 'order.placed' be modelled as?
Messages and events can usually be exchanged freely.