Skip to main content

Notification Event Correlation

Summary

Correlation is carried end to end from the publisher's AMQP property into persisted messages and audit rows, and a tracing activity is started per dispatch. One verified gap: the envelope's fallback correlation value is not the value that gets persisted.

Audience

Engineers, DevOps engineers, architects, QA, support and security reviewers.

Correlation lifecycle

Wire propagation

The shared event bus writes the correlation identifier twice: as the AMQP correlation-id property and as a CorrelationId header. Blank values are filtered out before headers are written.

The consumer reads the property first and falls back to the header, so either alone is sufficient. When neither is present the envelope's correlation field is null.

Activity propagation

The dispatcher opens an activity from a service-scoped activity source, named for the dispatch operation and the event type, with consumer activity kind. It tags the activity with the event type, the event identifier and the effective correlation identifier.

The activity's trace identifier is captured and threaded through every audit write for that event, so an audit row can be joined to a distributed trace. When no listener is registered the activity is null and the trace identifier is simply null — tracing is optional and its absence is handled.

The activity source is registered with the tracer at startup, so it participates in the platform's observability configuration.

The effective-correlation gap

The envelope exposes a computed property that substitutes the event identifier when the producer sent no correlation identifier. It is used for the activity tag only.

Every persistence path — messages, audit rows and the idempotency ledger — writes the raw nullable field instead. An event published without a correlation identifier is therefore traced under a substituted value but persisted with a null correlation, so the audit query's correlation filter cannot find it.

This is a verified inconsistency between the tracing view and the stored view.

HTTP correlation

For requests that enter through the API rather than the broker, correlation comes from a different mechanism: middleware resolves or generates an identifier, stamps it on the request items and the response header, and opens a logging scope carrying it. That value flows to logs but is not joined to the event correlation identifier — the test-dispatch hook builds its envelope from the request body, generating a compact identifier when the caller supplies none.

Causation

The envelope carries a causation identifier parsed from its header, and the publisher writes it for typed contracts. Nothing in Notification reads it — it is never persisted, tagged or logged. Causation chains cannot be reconstructed from Notification data.

Classification

Foundation — propagation and tracing are Implemented; the persisted-correlation fallback and causation use are Not implemented.

Requires confirmation

Whether persisted correlation should use the effective fallback, and whether causation is intended to be recorded, require confirmation.

See Also

Keywords

  • Notification database
  • Correlation
  • Draft database documentation

Source References

  • microservices/src/notification-service/Messaging/NotificationEventEnvelope.cs
  • microservices/src/notification-service/Application/NotificationDispatcher.cs
  • microservices/src/notification-service/Application/NotificationTelemetry.cs
  • microservices/src/shared-kernel/Middleware/CorrelationIdMiddleware.cs
  • microservices/src/notification-service/Program.cs
  • microservices/src/notification-service/Domain/NotificationEntities.cs

Revision Information

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