Skip to main content

Notification Event Envelope

Summary

NotificationEventEnvelope is a sealed record of 11 fields plus one computed property. It is the service's normalised view of a delivery, built from AMQP properties, headers and the body.

Audience

Engineers, architects, QA, support and security reviewers.

Reference Content

The verified reference material for this topic is set out in the sections below.

Fields

FieldTypeSource on the wireUsed downstream
EventIdGUIDMessage id, else the EventId headerYes — idempotency key
EventTypestringType property, else the EventType header, else the routing keyYes — resolver switch
CorrelationIdstring?Correlation id property, else the CorrelationId headerYes — audit and messages
CausationIdstring?CausationId headerNo
TenantIdstring?TenantId headerYes — tenant scoping
UserIdstring?UserId headerNo
SourceServicestringSourceService header, else the literal unknownYes — idempotency ledger
OccurredAtUtctimestampOccurredAtUtc headerYes — staleness check
SchemaVersionintSchemaVersion headerNo
PayloadJsonstringThe message body, decoded as UTF-8Yes — deserialized per event
ForceFailboolx-force-fail headerYes — test affordance

Three fields — causation identifier, user identifier and schema version — are parsed onto the envelope and then never read by any downstream code. They are carried for future use.

Computed correlation

The record exposes an effective correlation identifier that falls back to the event identifier when the producer sent none, so correlation is never null for tracing purposes. Note that the raw nullable field is what gets persisted onto messages and audit rows; see correlation.

Parsing fallbacks

Every field has a defined fallback, so a malformed or sparse message still produces a usable envelope rather than an exception.

FieldFallback chain
Event identifierMessage id → header → newly generated GUID
Event typeType property → header → routing key
OccurrenceHeader → current instant
Schema versionHeader → 1
Source serviceHeader → unknown
CorrelationProperty → header → null

The event-identifier fallback matters. A message arriving with neither a message id nor an EventId header receives a freshly generated identifier, which is unique on every delivery. Such a message can never be recognised as a duplicate, so redelivery would reprocess it. See idempotency.

Header decoding

Header values arrive as byte arrays, strings or other objects. A decoder normalises all three: byte arrays are decoded as UTF-8, strings pass through, anything else uses its string representation, and null yields null.

Publisher-side symmetry

The shared event bus writes exactly the header set the consumer reads — event identifier, event type, correlation, causation, tenant, user, source service, occurrence and schema version — and additionally sets the message id, correlation id, type, content type, persistent delivery mode and a timestamp as AMQP properties.

Metadata entries with blank values are filtered out before headers are written, so an absent value produces a missing header rather than an empty one, which is why the consumer's fallbacks are needed.

Verified absence

The envelope carries no signature, no encryption marker, no content-type negotiation, no compression flag, no retry counter and no dead-letter reason.

Classification

Implemented.

Requires confirmation

Whether the three unused fields are intended to drive behavior requires confirmation.

See Also

Keywords

  • Notification database
  • Event Envelopes
  • Draft database documentation

Source References

  • microservices/src/notification-service/Messaging/NotificationEventEnvelope.cs
  • microservices/src/notification-service/Messaging/NotificationEventConsumer.cs
  • microservices/src/shared-kernel/Messaging/RabbitMqEventBus.cs
  • microservices/src/notification-service/Api/NotificationEndpoints.cs

Revision Information

  • Status: Draft
  • Last reviewed: 2026-07-21
  • Review cycle: Quarterly