Message
The unit of data exchanged between publishers and subscribers through a message broker.
A message is the unit of data that flows between publishers and subscribers. It's an envelope that carries a payload (the actual data) and metadata (like a unique ID, headers, or a correlation ID) through a Message Broker.
Events (OrderPlaced) and commands (CancelTraining) can both be messages. The difference is in semantics: events describe facts, commands express intent. But at the infrastructure level, they're all messages traveling through topics and queues.
A message typically has two parts: the payload and metadata. The payload is the serialized business data (often JSON or Protocol Buffers). The metadata includes things like a unique message ID, a Correlation ID for tracing, and timestamps. Some systems also support custom headers for routing or versioning.
Messages are not the same as the business concepts they carry. A message is the transport mechanism. The event or command inside it is the business concept.
When a subscriber receives a message, it must acknowledge it. Calling Ack() tells the broker the message was processed successfully. Calling Nack() signals a failure, and the broker redelivers the message. This acknowledgement mechanism is what makes At-Least-Once Delivery possible: messages keep coming back until someone confirms they've been handled.
References
- Distributed Transactions in Go: Read Before You Try — Explicitly defines the difference between events and messages. A message is the transport unit you publish to the Pub/Sub, similar to an HTTP request. An event is a specific message representing a fact, carried as the message payload.
- Introducing Watermill - Go event-driven applications library — Introduces the Watermill message abstraction with Publisher and Subscriber interfaces. Shows how handler functions receive and produce messages, and how middleware handles acknowledgment and error recovery.
- Live website updates with Go, SSE, and htmx — Uses Watermill's Pub/Sub interfaces to publish and subscribe to messages across the network. Shows the Publisher and Subscriber interfaces and how messages flow between backend services and the browser via SSE.
- Using MySQL as a Pub/Sub — Demonstrates implementing message publishing and subscribing with SQL databases. Defines any Pub/Sub with two methods: publishing a message to a topic and subscribing for messages from a topic.
- Watermill 1.4 Released (Event-Driven Go Library) — Discusses how a single failing message blocks other messages in most Pub/Subs. Introduces a universal requeuer with SQL-based poison queue for failed messages and delayed redelivery across all Pub/Subs.
- Durable Background Execution with Go and SQLite — Explains message acknowledgment patterns with at-least-once delivery. Shows that acknowledging the message only after all business logic completes ensures durability, and handlers must be idempotent to handle redelivery.
- SQLite Pub/Sub, Quickstart, and more — Watermill 1.5 Released — Shows how messages move between publishers and subscribers using SQLite tables. Demonstrates creating, publishing, and subscribing to messages with the standard Watermill Message type.
- Watermill 1.3 released, an open-source event-driven Go library — Describes three APIs for handling messages: raw Subscribe calls, Router with message handlers, and CQRS event/command handlers. Introduces handler groups for subscribing to multiple event types while preserving message ordering.
- Watermill v1.2 released — Introduces the Forwarder component for forwarding messages from one Pub/Sub to another (e.g., SQL to Kafka), and FanIn for merging messages from multiple topics into a single stream.
- Shipping an AI Agent that Lies to Production: Lessons Learned — Shows practical challenges of working with messages in a real-world application, including message ordering and streaming message chunks over Pub/Sub to deliver AI-generated responses.
- Event-Driven Architecture: The Hard Parts — Explicitly distinguishes events from messages: a message is the transport unit (like an HTTP request), and an event is the payload inside it. Discusses how message brokers are designed not to lose messages and the importance of acknowledgment.
- Synchronous vs Asynchronous Architecture — Explains that an event is a kind of message that states a fact. Discusses how publishing a message decouples you from consumers, and how using messages for RPC-style requests doesn't give the same decoupling benefits as events.
- Watermill: from a hobby project to 8k stars on GitHub — Describes Watermill as a library for building event-driven and message-oriented applications. Covers how the message abstraction evolved over 8,000+ stars and 100+ contributors.