Channels and preferences Recommended
Batch small updates into a digest
Collect low-urgency notifications over a window and send one summary, instead of one message per event.
How to do it
Put low-urgency events in a pending table keyed by user and digest. A scheduled job sends one message per user when the window closes, such as hourly or daily at 09:00 local time. Group by type, such as "5 new comments on 2 posts". Skip the digest when every item was already read in the app. Let people pick the window on the settings page.
Example
export async function sendDigests(now) {
for (const { userId, items } of await db.pending.dueGroupedByUser(now)) {
const unread = items.filter(item => !item.readAt);
if (unread.length) await send(userId, 'digest.activity', { count: unread.length, items: unread });
await db.pending.remove(items.map(item => item.id));
}
}
def send_digests(now):
for user_id, items in db.pending.due_grouped_by_user(now):
unread = [item for item in items if item.read_at is None]
if unread:
send(user_id, "digest.activity", {"count": len(unread), "items": unread})
db.pending.remove([item.id for item in items])
How to check
Create 10 comments for one user within an hour. The user gets one push or email that names all 10, and the pending table for that user is empty afterwards.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/channels-and-preferences/notification-digests.