Back to Case Studies

Seamless Notification Delivery System: The Pusher Solution

Feature Automated Push Notification Delivery
Stack
Flutter Next.js Firebase Messaging Pusher

Project Overview

The Seamless Notification Delivery System was designed to provide a fully automated and highly customizable push notification experience. The aim was to connect backend triggers with mobile app notifications, ensuring instant and efficient communication between users and the platform. Built for a client needing an advanced notification mechanism with real-time capabilities and personalized user experiences.

Workflow Overview

The following diagram illustrates the end-to-end workflow for the notification delivery system.

Event / Trigger
Cron Job Hook Manual
Backend · Next.js
Processes trigger · Routes message
Pusher
Real-time delivery
Firebase Messaging
FCM broadcast · Role-based targeting
Awesome Notifications
Custom channels · Sounds · Badges
Mobile App · Flutter
Display + local history saved

Workflow Steps

01 Event Triggering and Backend Processing

The workflow begins when an Event or Trigger occurs — either an automated cron job or a hook from an external action. The backend processes this trigger and initiates the necessary messaging through Firebase.

02 Triggering Firebase Messaging

The backend sends a trigger to Firebase Messaging, which broadcasts notifications. Firebase manages real-time data flow to ensure messages are delivered to the correct users instantly.

TypeScript
public async sendNotification({
  registrationTokens,
  title,
  body,
  data,
}: {
  registrationTokens: string[];
  title: string;
  body: string;
  data: any;
}) {
  const message: MulticastMessage = {
    data: { title, body, ...data },
    tokens: registrationTokens,
  };

  try {
    const response = await this.app.messaging().sendEachForMulticast(message);
    logger.info('Successfully sent message:', response);
    return response;
  } catch (error) {
    logger.info('Error sending message:', error);
    throw error;
  }
}

03 Broadcast via Awesome Notifications Package

Once Firebase has processed the message, it is broadcast through the Awesome Notifications Package. This package facilitates the creation of customized notifications, tailored to specific user preferences or roles.

04 Mobile App Reception and Data Handling

The Mobile App receives the notification and displays it according to user preferences. Each notification is also saved in the local database to provide a history of received messages.

Important Note The created notifications fully depend on the data layer of the notification rather than the notification layer payload. This ensures flexibility in customizing notifications and adding additional data parameters as needed.

Features and Solutions

01 Automated Trigger System

The system utilizes both manual and automated triggers. Notifications can be initiated through backend events, cron jobs, or manual actions by platform administrators. Notifications are divided based on user roles, allowing targeted, personalized messaging.

Dart
@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  await NotificationService().showNotification(message);
  await ElasticServcie().logEvent(
    MessageRecievedEvent(
      timestamp: DateTime.now(),
      message: message,
      isBackgroundMessage: true,
    ),
  );
}

02 Customized Notification Channels

The system allows the creation of custom channels with different sounds and visual configurations to suit specific user needs, making each notification type easily distinguishable.

Dart
final NotificationChannel highPriorityChannel = NotificationChannel(
  channelKey: 'high_priority',
  channelName: 'High Priority Notifications Channel',
  channelDescription: 'Notification channel for high priority notifications.',
  defaultColor: const Color(0xFF9D50DD),
  ledColor: Colors.white,
  playSound: true,
  importance: NotificationImportance.High,
  channelShowBadge: true,
  enableVibration: true,
  enableLights: true,
  vibrationPattern: highVibrationPattern,
  soundSource: "resource://raw/res_notification",
);

03 Integration with Firebase Messaging

We leveraged Firebase Messaging to facilitate real-time notifications. Firebase served as the bridge between the backend server and the mobile applications, broadcasting notifications quickly and reliably.

Dart
FirebaseMessaging.onMessage.listen((message) async {
  await Firebase.initializeApp();
  await NotificationService().showNotification(message);
  await ElasticServcie().logEvent(
    MessageRecievedEvent(
      timestamp: DateTime.now(),
      message: message,
    ),
  );
});

04 Real-Time Delivery with Pusher

Pusher was integrated to enhance the speed and reliability of notifications, especially during high traffic. Pusher guarantees every notification — manual or automated — is delivered in real time to all active devices.

05 Mobile App Integration

A Flutter-based Mobile App received customized notifications via the Awesome Notifications Package. Notifications were stored locally to ensure users always had easy access to their recent messages.

Dart
Future<void> navigateToMessage() async {
  final String? generalAccessToken = await _getGeneralAccessToken();
  if (generalAccessToken != null && generalAccessToken.isNotEmpty) {
    await AwesomeNotifications().resetGlobalBadge();
    if (Get.isRegistered<MessagesController>()) {
      await Get.find<MessagesController>().refreshData();
    }
    if (Get.currentRoute == homePageName) {
      Get.find<HomeController>().currentTabIndex(1);
      Get.find<HomeController>().tabController.index = 1;
    } else {
      Get.toNamed(permissionsPageName, arguments: {"homeTab": 1});
    }
  }
}

Challenges & Solutions

Challenge Creating notification channels that users can easily distinguish by type.

Solution Used the Awesome Notifications package to customize sounds, visual layouts, and channel identifiers — ensuring each notification type stands out clearly.

Challenge Establishing seamless connectivity between Firebase, backend logic, and the mobile app.

Solution Firebase served as an intermediary that handled all data flow smoothly between the backend and the Flutter app, abstracting away complexity.

Challenge Ensuring notifications were automated for different scenarios while maintaining a high level of personalization.

Solution The use of cron jobs, event-based hooks, and customized user roles ensured each notification was timely, relevant, and fully automated.

Impact

The implementation resulted in a highly efficient and automated notification process. The platform saw reduced operational costs through full automation, increased user engagement via real-time updates, and strong positive feedback on the customization and reliability of the notification system.