Here we are dealing with the Push Notifications powered by in-app chat and messaging platforms to intimate information in real-time. It’s often compared to SMS which more or less does the same job. But comparing SMS and push notification is something like comparing apples to oranges. Push notification in in-app or a messaging application creates an impactful engagement, user retention and conversational route to stay in touch with the user. The main purpose of this article is to expose the queueing layer used between the XMPP server and the push services (FCM, and APNS) in MirrorFly infrastructure, which handles bulk notifications very efficiently.
Enhanced Push Notification Delivery Across Platforms
Push notifications are vital when it comes to real-time chat applications. What good is a chat application, when you don’t receive important messages in time, right? Implementing push notifications reliably on different platforms require special attention because otherwise, notifications can be delayed or even lost in some cases.
We’ll see how MirrorFly delivers push notifications to clients in an efficient manner. What you might have already known, is that FCM will be used to deliver push to Android devices, and APNS for iOS devices. However, incorrect usage of those APIs might hinder the delivery of the notifications which will affect the user experience.
Moreover, dealing with notifications for groups or channels is a problem on a different scale. Bottlenecks are common when dealing with bulk push notifications, and when the services said above take time to respond, the application server will take a toll, and won’t be able to handle any notifications that are sent after.
We use a message queuing system, to handle the bulk notifications that are to be sent. This is where RabbitMQ comes in. The primary purpose of using RabbitMQ is to reduce the load on the XMPP server when dealing with push notifications. When large numbers of push have to be triggered directly from the XMPP server itself, it creates a bottleneck, which hinders the overall performance of the server, which results in delayed deliveries.
The core concept used from RabbitMQ is the AMQP protocol, which is the backbone of the queueing implementation.
The above diagram shows a simple version of how the publisher, (our application layer, which is XMPP server), produces the content ( the messages to be sent as push), and how the client (The Java implementation which receives the messages from the queue), handles the content.
The Java implementation takes care of sending the messages through the push service based on the platform.
The common and important concepts of the AMQP and the queueing implementation that are used are as follows.
Exchange and Exchange Types
Exchanges are AMQP 0-9-1 entities where messages are sent. Exchanges take a message and route it into zero or more queues. The routing algorithm used depends on the exchange types and rules called bindings. AMQP 0-9-1 brokers provide four exchange types:
Bindings are rules that exchanges use (among other things) to route messages to queues. To instruct an exchange E to route messages to a queue Q, Q has to be bound to E. Bindings may have an optional routing key attribute used by some exchange types. The purpose of the routing key is to select certain messages published to an exchange to be routed to the bound queue. In other words, the routing key acts like a filter.
Client-side implementations are platform-dependent and are implemented accordingly.
Android will receive push notifications, from the FCM server. And push notifications are classified based on priorities. For example, a call related notification will have a higher priority than a normal notification. And also call notifications should have the importance “now or never”. When a call notification cannot be delivered instantly, it doesn’t make sense to deliver it later. Instead, it will be sent as a “Missed call” notification with a different priority, which will be delivered whenever the user’s device meets the conditions to receive a push notification. Android clients with the latest android version will have the problem of notifications being delivered delayed. In some cases, the application will navigate the user to the application settings page, where they can change the importance of the notification, or change optimization settings to ensure instant delivery of notifications.
In iOS, handling push notifications gets a little tricky, as background processing is limited on iOS devices. We leverage the benefits of VOIP push that can be delivered, even when the application is terminated state. For call-related notifications, the VOIP push is always used. In some cases, the push notification itself will not be enough to deliver sufficient data to the client, and the client will have to fetch the relevant data. For that to happen, the application must be launched in the background, which is not possible with a normal push notification. On the other hand, a VOIP push launches the application in the background, which lets the developer fetch relevant data, and then he can show user-readable data as a local notification. A normal push is used when the application is online and running, and the VOIP push will be used when the application is terminated state.
Dealing with push notifications, not an easy task, but if architected properly, the implementation will have huge performance benefits. Well-targeted push notification has the potential to engage, retain and create new users to application or web. The MirrorFly Chat API allows inbuilt push notification functionality into their mobile and web applications.