Skip to main content

Notification Delivery Storage

Summary​

NotificationDeliveryAttempts records one append-only row per delivery attempt against a channel provider, including timing and any error.

Audience​

Engineers, architects, QA, support and security reviewers.

Reference Content​

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

Ownership​

Owned by NotificationDbContext. Written by the dispatcher's attempt recorder on every try and by the template test endpoint's live-send path. Read by the attempts endpoint.

Columns​

ColumnTypeConstraint
IdGUIDPrimary key
NotificationMessageIdGUIDPlain value, no constraint
AttemptNumberintOne-based
ChannelstringMax length 40, required
ProviderstringMax length 60, required
StatusstringMax length 40, required
ErrorstringMax length 2000, nullable
StartedOnUtctimestamp—
CompletedOnUtctimestamp—
DurationMslong—

Attempt status values are stored as plain strings drawn from a constants class: success, failed and skipped.

Indexes​

IndexColumnsUnique
IX_DeliveryAttempts_MessageIdmessageNo

There is no unique index on the message and attempt-number pair, so nothing structurally prevents two rows claiming the same attempt number for the same message.

Relationships​

None declared. NotificationMessageId is a plain GUID with no foreign key, no navigation property and no cascade rule. Attempt rows are not deleted when a message is — and no code path deletes either.

Truncation​

The error text is truncated in application code to the mapped maximum length before the row is added, so an oversized provider error is stored clipped rather than raising a length violation. This is one of only two places in the module where a value is defensively truncated; the other is the audit detail.

Timing​

The recorder captures a start timestamp, measures elapsed time with a stopwatch, and computes the completion timestamp by adding the measured duration to the start value rather than reading the clock a second time. The stored duration and the stored timestamp difference are therefore consistent by construction.

Lifecycle​

Append-only. Rows are never updated or deleted by any reviewed code path.

Classification​

Implemented.

Requires confirmation​

Whether a uniqueness guarantee on message and attempt number is intended requires confirmation.

See Also​

Keywords​

  • Notification database
  • Delivery Storage
  • Draft database documentation

Source References​

  • microservices/src/notification-service/Infrastructure/NotificationDbContext.cs
  • microservices/src/notification-service/Domain/NotificationEntities.cs
  • microservices/src/notification-service/Application/NotificationDispatcher.cs
  • microservices/src/notification-service/Api/NotificationEndpoints.cs
  • microservices/src/notification-service/Infrastructure/Migrations/20260705113059_InitialNotificationSchema.cs

Revision Information​

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