Skip to main content

Notification Event Limitations

Summary

Every limitation below is a verified property of the reviewed source, grouped by concern and cross-referenced to the page carrying the evidence.

Audience

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

Reference Content

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

Publishing

  • The service publishes no business event, so no module can react to a delivery outcome, failure or read.
  • No outbox exists; the shared outbox processor resolves to its no-operation implementation because no message store is registered.
  • No domain event, aggregate or event raiser exists — state changes are direct mutations.
  • The one publish path is the test hook, which accepts an arbitrary caller-supplied event type and places it on the shared platform exchange with no authorization.
  • Publishes are fire-and-forget: the mandatory flag is false and publisher confirms are not enabled, so a message routed to no queue is silently discarded and the publish still reports success.

Consumption

  • A broker outage produces an indefinite reconnect loop at warning level while the service continues to report healthy, so a service consuming nothing looks operational.
  • The consumer passes its stopping token into dispatch, so shutdown cancels in-flight processing mid-pipeline rather than draining it.
  • 32 of 42 events deserialize into service-local records with no compile-time link to the publisher's contract, so payload drift appears only as blank notification content.
  • Deserialization is tolerant and guards on few fields, so a malformed payload usually yields a skipped or blank notification rather than a detected error.
  • Events from unmapped modules are absorbed with a no-recipient outcome and no alert.

Broker

  • Dead-letter exchange and queue names are configured but referenced nowhere; the queue is declared with no arguments.
  • No message time-to-live, queue length limit, priority, alternate exchange or queue type is declared.
  • The queue name is shared by every instance with no single-active-consumer setting, so scaling out multiplies concurrency without ordering control.
  • Bindings are exact strings on a topic exchange, so no wildcard subscription exists and every new event type needs a code change.
  • The service asserts nothing about operator-applied broker policies, which are outside the repository.

Retry

  • Broker-layer redelivery is unbounded: any escaping exception requeues with no delivery-count check, no rejection path and no maximum.
  • Combined with the absent dead-letter wiring, a deterministically failing message loops indefinitely with no way to park it.
  • The uncaught unique-index violation on the idempotency ledger is one verified way to enter that loop.
  • In-process delivery retry holds the broker delivery un-acknowledged for the whole backoff sequence, extending the un-acknowledged window under failure.
  • No circuit breaker, no backoff at the broker layer and no poison-message quarantine exists.

Dead-letter

  • Configured but not wired — the two settings are unreferenced.
  • No dead-letter exchange, queue or binding is declared by the service.
  • No code consumes, inspects or drains a dead-letter destination.
  • Because the consumer always requeues rather than rejecting, no message can leave the queue except by succeeding.

Ordering

  • No ordering guarantee of any kind: no sequence number, partition key, single-active-consumer setting or reordering buffer.
  • Prefetch defaults to 5 and the handler is asynchronous and unserialised, so deliveries overlap.
  • Variable processing time and requeue both reorder completion relative to arrival.
  • Event families that imply a sequence can deliver notifications out of order with no detection or compensation.

Idempotency

  • The check-then-write window spans the entire pipeline including provider sends and retry delays, so concurrent redelivery can duplicate messages and deliveries.
  • The ledger row is written last, so a crash mid-processing guarantees full reprocessing on redelivery.
  • The unique-violation that ultimately rejects a duplicate ledger row is not caught and escapes as an unhandled exception.
  • A message arriving with no message id and no event-id header receives a freshly generated identifier per delivery and can never be recognised as a duplicate.
  • The ledger is never trimmed and cannot be safely trimmed, since an absent row is indistinguishable from an unprocessed event.
  • Idempotency covers events only — manual retry, the dispatch hook and template test sends create messages outside its protection.

Versioning

  • The schema version is carried end to end and never read; no version branch, check or rejection exists.
  • An unparseable or missing version header defaults to 1, indistinguishable from a genuine version 1.
  • No upcasting, no versioned contract types and no version segment in any routing key.
  • The event schema version is not persisted anywhere, so a stored message cannot be attributed to a contract version.
  • A breaking payload change produces silent content degradation rather than a failure signal.

Testing

  • No test project references the consumer, resolver, envelope or event bus.
  • Broker mode is the only automated exercise of the consumer, and it covers a subset of event types rather than all 42 bindings.
  • No test covers negative acknowledgement, requeue, the poison loop, the generated-identifier fallback, correlation propagation, ordering or the channel-override map.
  • No contract test pins any of the 14 payload shapes — the gap is widest for the 32 locally duplicated ones.

Observability

  • The persisted correlation identifier uses the raw nullable field rather than the effective fallback, so an event published without a correlation identifier is untraceable through the audit correlation filter.
  • The causation identifier and user identifier are parsed and never used, so causation chains cannot be reconstructed.

Classification

Verified limitations. The event surface is Transitional; published events, dead-letter processing and ordering are Not implemented; idempotency, retry, versioning, correlation and testing are Foundation or Partial.

Requires confirmation

Redelivery limits and poison-message handling, dead-letter intent, whether outbound events are planned, and contract ownership for the locally duplicated payloads all require confirmation.

See Also

Keywords

  • Notification database
  • Event Limitations
  • Draft database documentation

Source References

  • microservices/src/notification-service/Messaging/NotificationEventConsumer.cs
  • microservices/src/notification-service/Application/NotificationDispatcher.cs
  • microservices/src/notification-service/Application/NotificationOptions.cs
  • microservices/src/notification-service/Application/EventNotificationResolver.cs
  • microservices/src/notification-service/Messaging/NotificationEventEnvelope.cs
  • microservices/src/shared-kernel/Messaging/RabbitMqEventBus.cs
  • microservices/scripts/smoke-notification.ps1

Revision Information

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