Appearance
Configuration
All GrydNotifications settings are configured through GrydNotificationsOptions:
csharp
builder.Services.AddGrydNotifications(options =>
{
// ... configuration here
});GrydNotificationsOptions
Connection String
Required. PostgreSQL connection string for notification persistence and template storage.
csharp
options.UsePostgreSqlStorage("Host=localhost;Database=gryd_notifications;...");
// or
options.ConnectionString = "Host=localhost;Database=gryd_notifications;...";Feature Toggles
| Property | Type | Default | Description |
|---|---|---|---|
EnableTemplates | bool | true | Enables Scriban template engine |
EnableQueue | bool | true | Enables async queue processing. When false, sends synchronously |
PersistNotifications | bool | true | Persists notifications in the database for auditing |
NotificationRetentionDays | int | 90 | Days to retain sent/failed notifications before cleanup |
csharp
options.EnableTemplates = true;
options.EnableQueue = true;
options.PersistNotifications = true;
options.NotificationRetentionDays = 90;Email Options
Configure email sending via SMTP (MailKit).
csharp
options.Email.DefaultFrom = "noreply@myapp.com";
options.Email.DefaultFromName = "My Application";
options.Email.SmtpHost = "smtp.sendgrid.net";
options.Email.SmtpPort = 587;
options.Email.SmtpUseSsl = true;
options.Email.SmtpUsername = "apikey";
options.Email.SmtpPassword = "SG.xxxxxxxxx";Properties
| Property | Type | Default | Description |
|---|---|---|---|
DefaultFrom | string | "" | Default sender email address |
DefaultFromName | string? | null | Default sender display name |
SmtpHost | string? | null | SMTP server hostname |
SmtpPort | int | 587 | SMTP server port |
SmtpUseSsl | bool | true | Use SSL/TLS for SMTP connection |
SmtpUsername | string? | null | SMTP authentication username |
SmtpPassword | string? | null | SMTP authentication password |
MaxAttachmentSizeMb | int | 10 | Maximum attachment size per email (MB) |
MaxAttachmentsPerEmail | int | 5 | Maximum number of attachments per email |
MaxRecipientsPerEmail | int | 50 | Maximum recipients (To + Cc + Bcc) |
BulkBatchSize | int | 100 | Emails per batch in bulk operations |
BulkDelayBetweenBatches | TimeSpan | 1s | Rate limiting delay between batches |
Using SendGrid instead of SMTP
To use SendGrid's HTTP API instead of SMTP, install the provider package and configure the API key:
csharp
// Install: dotnet add package GrydNotifications.Infrastructure
// SendGrid uses the SMTP credentials with host smtp.sendgrid.net
options.Email.SmtpHost = "smtp.sendgrid.net";
options.Email.SmtpUsername = "apikey";
options.Email.SmtpPassword = "SG.your_api_key_here";Push Notification Options
Configure push notifications via Firebase Cloud Messaging (FCM).
csharp
options.Push.Enabled = true;
options.Push.DefaultTimeToLive = TimeSpan.FromHours(24);
options.Push.AutoRemoveInvalidTokens = true;Properties
| Property | Type | Default | Description |
|---|---|---|---|
Enabled | bool | true | Enables the push notification channel |
DefaultTimeToLive | TimeSpan | 24h | Default TTL for push messages |
MaxDeviceTokensPerMulticast | int | 500 | Max tokens per FCM multicast (FCM limit: 500) |
StaleTokenThreshold | TimeSpan | 90 days | Duration after which unused tokens are deactivated |
AutoRemoveInvalidTokens | bool | true | Auto-remove tokens reported as invalid by FCM |
Firebase Configuration
Place your Firebase service account JSON at the root of your project or configure the GOOGLE_APPLICATION_CREDENTIALS environment variable:
bash
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/firebase-adminsdk.json"In-App Notification Options
Configure the in-app notification channel (drawer/bell notifications + SignalR real-time).
csharp
options.InApp.Enabled = true;
options.InApp.EnableSignalR = true;
options.InApp.HubPath = "/hubs/notifications";
options.InApp.RetentionDays = 90;
options.InApp.MaxUnreadPerUser = 200;Properties
| Property | Type | Default | Description |
|---|---|---|---|
Enabled | bool | true | Enables in-app notification channel |
RetentionDays | int | 90 | Days to retain in-app notifications |
MaxUnreadPerUser | int | 200 | Max unread per user (oldest auto-marked as read) |
DefaultTimeToLive | TimeSpan? | null | Default TTL for notifications (null = no expiration) |
EnableSignalR | bool | true | Enables real-time delivery via SignalR |
HubPath | string | /hubs/notifications | SignalR hub endpoint path |
Retry Options
Configure retry policies for failed notification delivery.
csharp
options.Retry.MaxRetries = 3;
options.Retry.BackoffType = BackoffType.Exponential;
options.Retry.BaseDelay = TimeSpan.FromSeconds(5);
options.Retry.MaxDelay = TimeSpan.FromMinutes(5);
options.Retry.UseJitter = true;Properties
| Property | Type | Default | Description |
|---|---|---|---|
MaxRetries | int | 3 | Maximum retry attempts before dead-lettering |
BackoffType | BackoffType | Exponential | Backoff strategy |
BaseDelay | TimeSpan | 5s | Base delay for the first retry |
MaxDelay | TimeSpan | 5min | Maximum delay cap |
UseJitter | bool | true | Adds randomized jitter to prevent thundering herd |
NonRetryableReasons | HashSet<DeliveryFailureReason> | see below | Permanent failures that skip retry |
Backoff Types
| Type | Formula | Example (5s base) |
|---|---|---|
Fixed | baseDelay | 5s → 5s → 5s |
Linear | baseDelay × attempt | 5s → 10s → 15s |
Exponential | baseDelay × 2^attempt | 5s → 10s → 20s |
Non-Retryable Failure Reasons
By default, these permanent failures skip retry entirely:
InvalidRecipient— Email address doesn't existInvalidTemplate— Template syntax errorAuthenticationFailed— Provider credential error
Queue Options
Configure the in-memory notification processing queue (Channel<T>).
csharp
options.Queue.BatchSize = 10;
options.Queue.PollingInterval = TimeSpan.FromSeconds(5);
options.Queue.MaxConcurrency = 4;Properties
| Property | Type | Default | Description |
|---|---|---|---|
BatchSize | int | 10 | Notifications dequeued per batch |
PollingInterval | TimeSpan | 5s | Polling interval when queue is empty |
MaxConcurrency | int | 4 | Concurrent processors consuming the queue |
MessageExpiration | TimeSpan? | null | Max time in queue before discard (null = no limit) |
WARNING
The default queue uses Channel<T> in-memory. Messages are lost if the application restarts. For durable queuing in production, install GrydNotifications.Scheduling to delegate to GrydJobs.
Health Checks
csharp
// Basic registration
builder.Services.AddGrydNotificationsHealthChecks();
// With custom settings
builder.Services.AddGrydNotificationsHealthChecks(
name: "grydnotifications",
failureStatus: HealthStatus.Degraded,
tags: ["grydnotifications", "notifications", "ready"]);The health check monitors:
- Queue depth — Returns
Degradedif queue depth exceeds 10,000 - Infrastructure availability — Returns
Degradedon exceptions
http
GET /health
{
"status": "Healthy",
"entries": {
"grydnotifications": {
"status": "Healthy",
"description": "GrydNotifications is running.",
"data": {
"queueDepth": 42
}
}
}
}appsettings.json Reference
Complete configuration example:
json
{
"ConnectionStrings": {
"Notifications": "Host=localhost;Database=gryd_notifications;Username=postgres;Password=postgres"
},
"GrydNotifications": {
"EnableTemplates": true,
"EnableQueue": true,
"PersistNotifications": true,
"NotificationRetentionDays": 90,
"Email": {
"DefaultFrom": "noreply@myapp.com",
"DefaultFromName": "My App",
"SmtpHost": "smtp.sendgrid.net",
"SmtpPort": 587,
"SmtpUseSsl": true,
"SmtpUsername": "apikey",
"SmtpPassword": "SG.xxxxx",
"MaxAttachmentSizeMb": 10,
"MaxAttachmentsPerEmail": 5,
"MaxRecipientsPerEmail": 50,
"BulkBatchSize": 100,
"BulkDelayBetweenBatches": "00:00:01"
},
"Push": {
"Enabled": true,
"DefaultTimeToLive": "24:00:00",
"MaxDeviceTokensPerMulticast": 500,
"StaleTokenThreshold": "90.00:00:00",
"AutoRemoveInvalidTokens": true
},
"InApp": {
"Enabled": true,
"RetentionDays": 90,
"MaxUnreadPerUser": 200,
"DefaultTimeToLive": null,
"EnableSignalR": true,
"HubPath": "/hubs/notifications"
},
"Retry": {
"MaxRetries": 3,
"BackoffType": "Exponential",
"BaseDelay": "00:00:05",
"MaxDelay": "00:05:00",
"UseJitter": true
},
"Queue": {
"BatchSize": 10,
"PollingInterval": "00:00:05",
"MaxConcurrency": 4,
"MessageExpiration": null
}
}
}