Real-time notifications
Push notifications, in-app alerts, and multi-channel delivery with priority queues
Deliver notifications to users across multiple channels (push, email, in-app, SMS) with guaranteed delivery, priority routing, and smart deduplication.
The challenge
Notification systems need to handle multiple delivery channels, user preferences, rate limiting, and guaranteed delivery. Building this from scratch means managing queues, retries, templates, and delivery tracking across every channel.
How npayload solves it
Publish a notification once. npayload fans it out to every delivery channel the user has configured, with independent retries per channel.
Publish a notification
await npayload.messages.publish({
channel: 'notifications',
routingKey: `user.${userId}`,
priority: urgency === 'critical' ? 10 : 1,
payload: {
event: 'notification.send',
userId: 'usr_789',
title: 'Order shipped',
body: 'Your order #12345 has been shipped and will arrive by Friday.',
data: {
orderId: 'ord_12345',
trackingUrl: 'https://track.example.com/12345',
},
channels: ['push', 'email', 'in-app'],
},
});Subscribe delivery services
Each notification channel has its own subscriber with independent retry logic:
// Push notification service
await npayload.subscriptions.create({
channel: 'notifications',
name: 'push-sender',
type: 'webhook',
endpoint: { url: 'https://push-service.internal/send' },
delivery: {
retryPolicy: { maxAttempts: 3, initialDelayMs: 1000 },
},
});
// Email service
await npayload.subscriptions.create({
channel: 'notifications',
name: 'email-sender',
type: 'webhook',
endpoint: { url: 'https://email-service.internal/send' },
delivery: {
retryPolicy: { maxAttempts: 5, initialDelayMs: 5000 },
},
});
// In-app notification service
await npayload.subscriptions.create({
channel: 'notifications',
name: 'inapp-sender',
type: 'webhook',
endpoint: { url: 'https://inapp-service.internal/send' },
});If the email service is temporarily down, push and in-app notifications still deliver immediately. Email catches up when the service recovers.
Priority notifications
Critical notifications (security alerts, payment failures) should be delivered before routine ones:
// Critical: security alert
await npayload.messages.publish({
channel: 'notifications',
priority: 10,
payload: {
event: 'security.alert',
title: 'New login from unknown device',
body: 'Someone logged into your account from a new device in Berlin.',
channels: ['push', 'email', 'sms'],
},
});
// Routine: weekly digest
await npayload.messages.publish({
channel: 'notifications',
priority: 1,
payload: {
event: 'digest.weekly',
title: 'Your weekly summary',
channels: ['email'],
},
});Real-time in-app notifications
Use the React SDK for real-time in-app notifications:
import { useMessages } from '@npayload/react';
function NotificationBell({ userId }: { userId: string }) {
const { messages, isLoading } = useMessages(`notifications.${userId}`);
const unreadCount = messages.filter((m) => !m.metadata?.read).length;
return (
<div className="notification-bell">
<span className="badge">{unreadCount}</span>
<ul>
{messages.map((msg) => (
<li key={msg.gid}>{msg.payload.title}</li>
))}
</ul>
</div>
);
}Patterns
Per-user channels
For high-volume applications, create per-user notification channels:
// Create a channel per user
await npayload.channels.create({
name: `notifications.${userId}`,
description: `Notifications for ${userId}`,
});
// User's device subscribes to their channel
await npayload.subscriptions.create({
channel: `notifications.${userId}`,
name: `${userId}-push`,
type: 'webhook',
endpoint: { url: userPushEndpoint },
});Batching and digests
Use message groups to batch related notifications:
// Group by user for digest processing
await npayload.messages.publish({
channel: 'notification-digest',
groupKey: userId,
payload: {
event: 'activity.update',
title: 'New comment on your post',
},
});A digest consumer reads grouped messages and sends a single summary.
Why npayload for notifications
| Feature | Benefit |
|---|---|
| Fan-out | One publish, every channel receives independently |
| Priority queues | Critical alerts delivered first |
| Per-channel retries | Email retries do not block push delivery |
| Circuit breaker | Protects failing delivery services |
| Real-time hooks | In-app notifications via React SDK |
| DLQ | Never lose a failed notification |
| Routing keys | Filter by user, event type, or priority |
Next steps
- Publishing guide for batch and priority publishing
- Subscriptions for delivery configuration
- React SDK for real-time in-app notifications
Was this page helpful?