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