Skip to content

Push Notification System

fulleni edited this page Feb 17, 2026 · 1 revision

This document provides a comprehensive technical overview of the server-side Push Notification System, detailing its value proposition, architectural flow, and resilience mechanisms.

1. Feature Value Proposition

The Push Notification System is engineered for flexibility, scalability, and high relevance, providing significant commercial and technical advantages.

  • Multi-Provider Support: The architecture is decoupled from any single push notification provider. It supports both Firebase Cloud Messaging (FCM) and OneSignal out-of-the-box. The active provider is determined by a single primaryProvider key in the RemoteConfig, allowing administrators to switch between services without a server redeployment. This avoids vendor lock-in and provides operational flexibility.

  • Hyper-Targeted Notifications: The System moves beyond simple "all users" broadcasts. It enables users to create granular SavedHeadlineFilter subscriptions based on any combination of Topics, Sources, and Countries. When a "breaking news" event occurs, the System dispatches notifications only to users whose specific filter criteria match the event, dramatically increasing relevance and user engagement.

  • In-App Notification Center: Every push notification sent is also persisted as an InAppNotification document in the database. This powers a client-side "inbox" or notification center, ensuring users can review important alerts they may have missed. These documents are automatically pruned after 90 days via a TTL index to manage data volume.

  • Automated List Hygiene: The System includes a robust, automated cleanup mechanism. When a provider (FCM or OneSignal) reports a device token as invalid (e.g., the app was uninstalled), the corresponding PushNotificationDevice document is automatically deleted from the database. This self-maintaining process improves delivery efficiency and keeps the device registry clean.

2. Architecture Trace

The system follows a precise, multi-stage process to deliver a breaking news notification from a headline trigger to a user's device.

  1. Trigger & Configuration:

    • The flow begins when DefaultPushNotificationService.sendBreakingNewsNotification is invoked with a Headline object.
    • It immediately fetches the global RemoteConfig to check if pushNotifications.enabled is true and if the breakingOnly delivery type is active. If not, the process aborts.
    • It identifies the primaryProvider (e.g., firebase) from the config.
  2. Client Selection & Validation:

    • The System selects the corresponding IPushNotificationClient (FirebasePushNotificationClient or OneSignalPushNotificationClient).
    • A critical validation step ensures the selected client was successfully initialized (i.e., its API credentials were provided in the environment). If not, the process aborts with a severe error, preventing runtime failures.
  3. User & Criteria Matching:

    • A paginated query is sent to the user_content_preferences collection to find all users with at least one filter subscribed to breakingOnly notifications.
    • The System then iterates through this list in-memory, applying the _matchesCriteria logic. This function compares the incoming Headline against each of the user's SavedHeadlineFilters. A filter matches if:
      • Its topic list is empty (wildcard) OR contains the headline's topic.
      • Its source list is empty (wildcard) OR contains the headline's source.
      • Its country list is empty (wildcard) OR contains the headline's event country.
    • The result is a final set of eligibleUserIds.
  4. Device Fetching & Filtering:

    • A single bulk query fetches all PushNotificationDevice documents where the userId is in the eligibleUserIds set.
    • This device list is further filtered to include only those that have a registered token for the system's primaryProvider.
  5. Payload Preparation & Persistence:

    • The System constructs a PushNotificationPayload from the headline's data. It intelligently omits Base64-encoded images to avoid exceeding payload size limits.
    • For each eligible user, a unique InAppNotification document is created and persisted to the database. This operation happens in parallel for all users.
  6. Dispatch & Cleanup:

    • The System dispatches all notifications in parallel using the selected client's sendBulkNotifications method.
    • A then() callback is attached to each send operation. Upon completion, this callback triggers the _cleanupInvalidDevices method in a fire-and-forget manner, passing along any tokens the provider reported as invalid.
    • The cleanup method finds the corresponding device documents and deletes them.

3. Resilience Profile

The System is designed with multiple layers of resilience to ensure stable and predictable operation.

  • Configuration-Driven Abortion: The System aborts gracefully at the earliest possible stage if the feature is disabled via RemoteConfig, preventing unnecessary database queries.

  • Client Initialization Check: A hard check prevents the System from attempting to use a push notification client that failed to initialize due to missing credentials, avoiding runtime null exceptions.

  • Graceful Empty-Set Handling: The flow includes explicit checks for empty results at every major step (no subscribers, no matching users, no registered devices). In each case, it logs an informative message and aborts cleanly.

  • Provider-Specific Batching: The FirebasePushNotificationClient and OneSignalPushNotificationClient are aware of their respective API limits. They automatically chunk large lists of device tokens into batches of the appropriate size (500 for FCM, 2000 for OneSignal) to ensure reliable delivery.

  • Invalid Token Pruning: The automated cleanup of invalid tokens is a key resilience feature. By removing stale registrations, the system reduces noise in future send operations and maintains a high-quality device list.

  • Error Isolation: The use of Future.wait with individual catchError handlers in the FirebasePushNotificationClient ensures that the failure of a single notification send does not halt an entire batch. In the main System, the cleanup process is unawaited (fire-and-forget) so that any potential failure in deleting a token does not impact the primary notification workflow.

Clone this wiki locally