CodePark/ questions / Message design, schemas & versioning
START PRACTICINGPRACTICE
Backend question · Message queues & streaming › Message design, schemas & versioning

Besides the business payload, what metadata should every message carry, and why?

{
  "id": "0b7c6a8e-3d1f-4c2a-9b55-1f2e8d7c4a10",
  "type": "OrderPlaced",
  "version": 2,
  "occurredAt": "2026-03-14T10:22:05.120Z",
  "source": "order-service",
  "correlationId": "req-7f3a",
  "causationId": "cmd-55e1",
  "data": { "orderId": "o-1001", "total": 129.9 }
}

Every message should carry an id, a type and version, an event time, a source, and correlation and causation ids. Each one has a job:

  • id: a unique id. Consumers use it to deduplicate redeliveries, so they don't process the same message twice.
  • type and schema version: they let a consumer send the message to the right handler. They also tell it how to parse the message while several versions are live.
  • occurredAt: when the event happened in the business sense. This is different from when it was published or consumed. It matters for ordering checks and for late data.
  • source: the name of the service that produced the message. It helps with debugging and shows who owns the message.
  • correlationId: one id shared by every message and log line from the same user request or workflow. It ties them together.
  • causationId: the id of the message that directly caused this one. With it, you can rebuild the chain of messages.

Put this metadata in a consistent envelope (a standard wrapper around the payload) or in message headers. CloudEvents is a standard for exactly this envelope.

  • A unique id lets consumers deduplicate messages.
  • The type and version let consumers route and parse the message.
  • The event time is kept separate from the processing time.
  • The source shows who owns the message and helps debugging.
  • Correlation and causation ids let you trace a request across messages.