Skip to main content

What the notification system does

In-app notifications appear in the bell icon in the top navigation bar. The unread count badge updates via polling every 30 seconds. Clicking the bell opens a panel listing recent notifications, each with a timestamp and optionally a link to the relevant page. Notifications are created automatically when relevant backend events occur — you do not call a notification API from the frontend. The backend creates notifications as part of command handlers. Users see them the next time their browser polls. All notifications are tenant-scoped. A user receives notifications from their currently active tenant only. If they switch tenants, they see that tenant’s notifications.

How notifications are created

INotificationService provides two methods:
Both methods automatically invalidate the Redis unread count cache for the affected users.

Notification types

Unread count optimization

The unread count endpoint (GET /api/v1/notifications/unread-count) is called by the frontend every 30 seconds. Without caching, this would be a database query on every poll for every logged-in user. Instead, the count is cached in Redis per user-tenant combination:
When a new notification is created or a notification is marked as read, the cache for the affected user is invalidated immediately. The next poll hits the database and re-caches the count. This means the unread count is at most 30 seconds stale in the worst case (if a notification arrived just after a poll), but typically updates within one poll cycle after the cache is invalidated.

How to add a new notification type

Notification security

Global query filters on the Notification entity ensure users cannot read other tenants’ notifications:
Both conditions must match. A user cannot read another user’s notifications within the same tenant, and cannot read any notifications from a different tenant.