Appearance
Flow, Persistence, And Retry
This page explains what happens after a notification is sent and how the database records should be interpreted.
HTTP Flow
Queue Flow
Request Lifecycle
NotificationRequest is the logical send attempt.
| Status | Meaning |
|---|---|
Pending | Created but not processing. |
Scheduled | Scheduled for future processing. |
Processing | Persisted and being sent. |
Sent | Provider accepted the send attempt. |
Delivered | Provider or status job confirmed delivery. |
Failed | Send attempt failed. |
Cancelled | Reserved status for cancelled requests. |
Important fields:
| Field | Meaning |
|---|---|
ChannelType | Notification channel. |
Subdomain | Tenant context. Empty string can appear for source-system or missing tenant paths. |
UserId | Target or current user when available. |
ApplicationTarget | Target application for push. |
PayloadJson | Original serialized payload. |
MetadataJson | Extracted searchable metadata. |
RenderedContent | Rendered email body when set. |
SourceSystem | Source-system sender identity as string. |
RetryCount | Incremented when the request fails. |
ErrorSummary | Failure summary. |
Delivery Lifecycle
NotificationDelivery is the provider-recipient attempt.
| Status | Meaning |
|---|---|
Pending | Delivery row exists but provider has not accepted it. |
Sent | Provider accepted it. |
Delivered | Provider confirmed delivery. |
Failed | Provider or service failed the delivery. |
Expired | Delivery expired. |
Rejected | Provider rejected it. |
Bounced | Email-style bounce. |
Opened | Recipient opened it. |
Clicked | Recipient clicked it. |
Important fields:
| Field | Meaning |
|---|---|
NotificationRequestId | Parent request. |
RecipientType | Device token, email address, or phone number. |
RecipientIdentifier | Email, phone number, or device token. |
ProviderType | Provider enum or string. |
ProviderMessageId | Provider message identifier when available. |
RequestPayload | Provider-facing request payload snapshot. |
ResponsePayload | Provider response snapshot. |
ErrorMessage, ErrorCode | Failure diagnostics. |
Tables
Entities are mapped under the SQL Server schema:
text
NotificationCore tables:
| Table | Entity |
|---|---|
[Notification].[NotificationRequest] | NotificationRequest |
[Notification].[NotificationDelivery] | NotificationDelivery |
[Notification].[NotificationChannelConfig] | NotificationChannelConfig |
[Notification].[DeviceRegistration] | DeviceRegistration |
[Notification].[WhatsAppTemplate] | WhatsAppTemplate |
[Notification].[WhatsAppProvisioningOperation] | WhatsAppProvisioningOperation |
Metadata Extraction
When a NotificationRequest is added, NotificationMetadataInterceptor extracts metadata by channel:
| Channel | Extracted examples |
|---|---|
| Push | title, Arabic title, body, route URL, module, service, setting type. |
| subject, body, module, service, setting type. | |
| SMS | body, module, service, setting type. |
| module, service, setting type, entity id/type, template metadata. |
Notification Center queries use this metadata to build list responses and filters.
Retry Behavior
Retry is handled by RetryNotificationCommandHandler.
Rules:
- The original notification must exist.
- The selected channel config must exist.
NotificationChannelConfig.EnableRetrymust be true.- The original persisted payload is deserialized by channel-specific deserializers.
- The orchestrator sends the payload again.
- A new
NotificationRequestis created for the retry attempt. - The response includes both the original notification id and the new notification id.
Email retry has one special behavior: if RenderedContent exists, retry uses that rendered body and disables template rendering/layout to avoid rendering the template differently later.
Push Persistence Detail
Push creates a request per target user. Device-token deliveries are created after device resolution. If no matching active and valid devices exist, the request is marked failed.
When FCM returns invalid-token errors, matching DeviceRegistration rows are marked invalid so future sends skip them.
WhatsApp Status Detail
When WhatsApp send succeeds and T2 returns a provider message id, the service:
- updates the delivery with the provider message id
- schedules
WhatsAppMessageStatusJob - checks status later through T2
This is why WhatsApp may be Sent before it becomes Delivered or Failed.
Troubleshooting Checklist
If a notification fails:
- Find the
NotificationRequestby id. - Check
Status,ErrorSummary,ChannelType,Subdomain,SourceSystem, andRetryCount. - Check related
NotificationDeliveryrows. - Inspect provider
RequestPayloadandResponsePayload. - Verify an active channel config exists for the effective context.
- Verify provider credentials are valid.
- For push, verify active valid device tokens exist for the user, platform, and application target.
- For WhatsApp, verify the template exists locally, has
SyncStatus = Approved, and has a T2 template id.