If you are a user of Firebase Cloud Messaging (FCM), you know that there are many different ways to send messages. You can target an application on a device, or target millions of them through the topics API. FCM APIs tell you if there was a failure during the acceptance of the request by returning an error code and an explanation for the failure, but this only covers the part of the request between you and the FCM backend. What happens after FCM accepts your message request?
In this post, we will look into the Firebase Cloud Messaging infrastructure and how messages are actually delivered to devices.
When FCM returns a successful response to your API request, it simply means that FCM will start trying to deliver this message to the device or to the service responsible for delivering the message to the device (for example: Apple Push Notification service for delivery to iOS devices or Mozilla Push Service for delivery to Firefox browsers). It will try this until:
1. The message expires
You can set message expiry through the API. The maximum time that FCM will retry is 28 days, which is the default value.
2. The requested message is superseded by another message
You can set collapse keys to replace the message with newer versions. An example use case would be a sports app that updates users with the latest score. Only the most recent message is relevant.
3. The device has not been online for more than a month
If FCM has information about the device connection and knows that the device hasn't been online for more than a month, FCM will accept the message but will not actually try to deliver it. If the device comes back online FCM will notify the app that pending messages were deleted:
- When the device gets back online, FCM will call onDeletedMessages() on Android.
- When the app is opened, FCM will trigger FIRMessagingMessagesDeletedNotification on iOS to notify the app that pending messages were deleted.
Note: If the time to live of the pending messages has expired, the above functions will not be triggered.
There are many factors that affect the actual delivery of the message to the device and the amount of information FCM can provide about the delivery.
Common Message Delivery Factors
1. The device is offline:
FCM cannot deliver the message if the device is not online. There are many devices that go offline, and some never come back online. Messages for applications on these devices will continue to be accepted by FCM, but will not be delivered unless the device comes back online.
2. Message priority
Android Message Delivery Factors
1. Doze Mode
If the device is in doze mode, FCM will hold on to normal priority messages until the device is out of doze mode. High priority messages will be sent out right away, but still are restricted by the Android app standby bucket policy on the device (for Android P and onwards).
2. App Standby Buckets
Starting from Android P, all applications adhere to app standby buckets. So even if you're setting the priority of your message to high, it might be delayed by the device if you don't have enough quota to wake the application up. See here for more information.
3. Background Restrictions
Android has limitations on what apps can do while running in the background. If your application is force-stopped or does not adhere to these limitations, the message may not be delivered to your application.
4. User-initiated Background Restrictions
FCM will not deliver messages to apps which were put into background restriction by the user.
5. Uninstalled application
When FCM attempts to deliver the message to the device and the application was uninstalled, the device will discard that message right away and invalidate the registration token. Future attempts to send a message to that device will result in a 'NotRegistered' error in the API response.
Note: If you'd like to analyze message delivery events for your project, you can do so by exporting FCM data into BigQuery.
iOS Message Delivery Factor
On iOS, there are two ways in which FCM can send a message to a device:
1. APNS channel
The most common way is sending the message via APNs. If you're using the FCM v1 HTTP API to request a message delivery or if you're using the legacy FCM API to send display messages, FCM will contact APNs to deliver the notification. After APNs accepts the message request, APNs is responsible for delivering the notification to the device. In this case, FCM on its own does not collect any delivery information and messages sent through APNs are subject to the same types of message delivery factors as other APNs messages. See here to learn more about factors that affect delivery to iOS devices through APNs.
2. FCM direct channel
The other way you can send messages to iOS devices is through the FCM direct channel. If you're using the legacy FCM API to send data only messages and if you have enabled direct channel connections through the shouldEstablishDirectChannel method, the messages will be delivered through a direct FCM channel. The FCM backend uses a message queue to keep track of pending messages when the app is in the background or closed. When the app goes to the foreground and the connection is re-established, the channel will automatically send pending messages to the client until it gets an acknowledgement from the client.
Note: If you'd like to access iOS notification delivery information for display notifications, you can use the FCM Reporting Dashboard. This dashboard leverages Google Analytics for Firebase data sharing features to collect delivery information through Firebase Android and iOS SDKs for display notifications.
Web Message Delivery Factors
1. Android Restrictions
If the web application is running on a browser on Android, all the restrictions defined under 'Android Factors' will apply to Web as well.
2. Push Services
If you're delivering a push notification to a web application that's running on a Push API supported browser that is using a different push service for the delivery of the messages, FCM will actually hand the message over to the push service for delivery. After this handoff, it's the push service's responsibility to deliver the message, and different restrictions may apply depending on the push service.