Notification Retry and Redelivery
Summary
Two independent retry mechanisms exist and they operate at different layers: a bounded in-process delivery retry inside the dispatcher, and an unbounded broker requeue in the consumer.
Audience
Engineers, architects, QA, support, DevOps engineers and security reviewers.
Retry and redelivery
Layer one — in-process delivery retry
Owned by the retry policy and driven by the dispatcher. Bounded by a configurable maximum attempt count defaulting to 3, with an exponential delay computed as the base delay multiplied by the backoff factor raised to the attempt index; attempt one has no delay. Defaults are 200 milliseconds and a factor of 2.
Each attempt writes an attempt row. Exhausting attempts marks the message failed and audits it — and completes normally. A permanently undeliverable notification therefore does not cause the event to be requeued.
Delays are awaited in process, so the broker delivery stays un-acknowledged for the whole retry sequence, and a cancellation during a delay stops the loop.
Layer two — broker redelivery
Owned by the consumer. Any exception escaping dispatch is logged and the delivery is negatively acknowledged with requeue set to true.
This is intended for infrastructure faults — the source comment names a database outage — where retrying later is right.
Unbounded requeue
There is no delivery-count check, no redelivery-limit header inspection, no rejection without requeue and no bounded attempt tracking at the consumer layer.
A message that fails deterministically — a payload that reliably breaks persistence, or the unique-violation path described in idempotency — is requeued indefinitely. Because the queue has no dead-letter arguments, there is nowhere for it to go. The result is a hot loop bounded only by how fast the broker redelivers, visible as repeated error logs.
This is the most operationally significant event limitation in the module.
Interaction with idempotency
Requeue and idempotency partly compensate. If the failure happened after the ledger row was written, redelivery is suppressed as a duplicate and acknowledged. If it happened before — which is the common case, since the ledger is written last — redelivery reprocesses fully.
Manual retry
A separate, operator-driven path re-drives one message by identifier through the same bounded loop. It does not involve the broker and is documented in the API and database sections.
Verified absence
No retry queue, no delay queue, no scheduled redelivery, no exponential backoff at the broker layer, no circuit breaker, no poison-message quarantine and no maximum-redelivery policy exists in the reviewed source.
Classification
Foundation — bounded delivery retry is Implemented; broker-layer redelivery control is Not implemented.
Requires confirmation
Whether a redelivery limit and poison-message handling are planned requires confirmation.
Related Articles
See Also
Keywords
- Notification database
- Retry & Redelivery
- Draft database documentation
Source References
microservices/src/notification-service/Application/NotificationDispatcher.csmicroservices/src/notification-service/Application/RetryPolicy.csmicroservices/src/notification-service/Messaging/NotificationEventConsumer.csmicroservices/src/notification-service/Application/NotificationOptions.cs
Revision Information
- Status: Draft
- Last reviewed: 2026-07-21
- Review cycle: Quarterly