FCM typically delivers messages immediately after they are sent. However, this might not always be possible. For example, the device could be unavailable or FCM might intentionally delay messages to prevent an app from consuming excessive resources and negatively affecting battery life.
In these cases, FCM stores the message and delivers it as soon as possible. While this is fine in most cases, there are some apps that require notifications to be sent without delay. For example, a notification for an incoming call or an invitation to an event.
On Android and Web, you can specify the maximum lifespan of a message. The value must be a duration from 0 to 2,419,200 seconds (28 days), and it corresponds to the maximum period of time that FCM stores and attempts to deliver the message. By default, requests that don't contain this field, last for a maximum period of four weeks.
On iOS, you can set the apns-expiration
header in the
ApnsConfig
object. For more details, refer to Apple's documentation on Sending
notification requests to
APNs.
Here are some possible uses for this feature:
- Video chat incoming calls
- Expiring invitation events
- Calendar events
Another advantage of specifying the lifespan of a message is that
FCM doesn't apply collapsible message throttling to messages with a
time to live value of 0 seconds. Keep in mind that a ttl
value of 0 means
messages that can't be delivered immediately are discarded. However, because
such messages are never stored, this provides the best latency for sending
notification messages.
Here is an example of a request that includes ttl:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
},
"apns":{
"headers":{
"apns-expiration":"1604750400"
}
},
"android":{
"ttl":"4500s"
},
"webpush":{
"headers":{
"TTL":"4500"
}
}
}
}
Lifetime of a message
When an app server posts a message to FCM and receives a message ID back, it doesn't mean that the message was already delivered to the device. Instead, it means that it was accepted for delivery. When the message is delivered depends on many factors.
If the device is connected but in Doze, a low priority message is stored by
FCM until the device is out of Doze. If the collapse_key
is set, and
there's an existing message with the same collapse
key and
registration token waiting for delivery, the old message is discarded and then
new message takes its place. However, if the collapse key is not set, both the
new and old messages are stored for future delivery.
If the device isn't connected to FCM, the message is stored until a
connection is established. When a connection is established, FCM
delivers all pending messages to the device. If the device never gets connected
again, the message eventually times out and is discarded from FCM
storage. The default timeout is four weeks, unless the ttl
flag is set. If the
app has been uninstalled when FCM attempts to deliver a message to the
device, FCM discards that message right away and invalidates the
registration token. Future attempts to send a message to that device results in
a NotRegistered
error.
For Android devices, if the device hasn't connected to FCM for more
than one month, FCM still accepts the message but immediately discards
it. If the device connects within four weeks of the last data message you sent
to it, your client app receives the
onDeletedMessages()
callback.
To get more insight into the delivery of messages on Android or Apple platforms, you can use the FCM reporting dashboard, which records the number of messages sent and opened on Apple and Android devices, along with data for impressions for Android apps.