Firebase Cloud Messaging (FCM) offers a broad range of messaging options and capabilities. The information in this page is intended to help you understand notification messages and data messages and what you can do with them using FCM's options.
Message types
With FCM, you can send two types of messages to clients:
- Notification messages, sometimes thought of as "display messages."
- Data messages, which are handled by the client app.
A notification message is the more lightweight option, with a 2KB limit and a predefined set of user-visible keys. Data messages let developers send up to 4KB of custom key-value pairs. Notification messages can contain an optional data payload that is delivered when users tap on the notification.
| Use scenario | How to send | |
|---|---|---|
| Notification message | FCM automatically displays the message to end-user devices on behalf of the client app. Notification messages have a predefined set of user-visible keys and an optional data payload of custom key-value pairs. |
|
| Data message | Client app is responsible for processing data messages. Data messages have only custom key-value pairs. | In a trusted environment such as Cloud Functions
or your app server, use the
Admin SDK or or the
HTTP and XMPP APIs: Set the data key only. Can be either collapsible or non-collapsible. |
Use notification messages when you want FCM to handle displaying a notification on your client app's behalf. Use data messages when you want to process the messages on your client app.
FCM can send a notification message including an optional data payload. In such cases, FCM handles displaying the notification payload, and the client app handles the data payload.
Notification messages
For testing or for marketing and user re-engagement, you can send notification messages using the Notifications composer.
To programatically send notification messages using the Admin SDK or the
FCM protocols, set the notification key with the
necessary predefined set of key-value options for the user-visible
part of the notification message. For example, here is a JSON-formatted
notification message in an IM app. The user can expect to see a
message with the title "Portugal vs. Denmark" and text "great match!" on the device:
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
}
}
Notification messages are delivered to the notification tray when the app is in the background. For apps in the foreground, messages are handled by these callbacks:
didReceiveRemoteNotification:on iOSonMessageReceived()on Android. Thenotificationkey in the data bundle contains the notification.
See notification payload support for the full list of predefined keys available for building notification messages.
Data messages
Set the data key with your custom key-value pairs to
send a data payload to the client app. Data messages can have a 4KB maximum payload.
For example, here is a JSON-formatted message in the same IM app as above, where the
information is encapsulated in the data key and the client app is expected to interpret the content:
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data" : {
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
},
}
On iOS, FCM stores the message and delivers it only
when the app is in the foreground and has established a FCM
connection. On Android, a client app receives a data message in
onMessageReceived() and can handle the key-value pairs
accordingly.
Note these further platform-specific details:
-
On Android, the data payload can be retrieved in the Intent used to launch your activity.
-
On iOS, the data payload is found in
didReceiveRemoteNotification:.
Notification messages with optional data payload
Both programatically or via the Firebase console, you can send notification messages that contain an optional payload of custom key-value pairs. In the Notifications composer, use the Custom data fields in Advanced options.
App behavior when receiving messages that include both notification and data payloads depends on whether the app is in the background or the foreground—essentially, whether or not it is active at the time of receipt.
- When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
- When in the foreground, your app receives a message object with both payloads available.
Here is a JSON-formatted message containing both the notification key and the data key:
{
"to" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
},
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
Non-collapsible and collapsible messages
A non-collapsible message denotes that each individual message is delivered to the device. A non-collapsible message delivers some useful content, as opposed to a "ping" to the mobile app to contact the server to fetch data. Messages are non-collapsible by default except for notification messages, which are always collapsible.
Some typical use cases of non-collapsible messages are chat messages or critical messages. For example, in an IM app, you would want to deliver every message, because every message has different content.
There is a limit of 100 messages that can be stored without collapsing. If the limit is reached, all stored messages are discarded. When the device is back online, it receives a special message indicating that the limit was reached. The app can then handle the situation properly, typically by requesting a full sync from the app server.
A collapsible message is a message that may be replaced by a new message if it has yet to be delivered to the device.
Two common use cases of collapsible messages are send-to-sync messages and notification messages. A send-to-sync message is a "ping" that tells a mobile app to sync data from the server. An example would be a sports app that updates users with the latest score. Only the most recent message is relevant.
To mark a message as collapsible, include the
collapse_key parameter in
the message payload. FCM allows a maximum of four different collapse
keys per device to be used by the app server
at any given time. In other words, the FCM connection server can
simultaneously store four different collapsible send-to-sync messages per
device, each with a different collapse key. If you exceed this number,
FCM only keeps
four collapse keys, with no guarantees about which ones are kept.
Which should I use?
Collapsible messages are a better choice from a performance standpoint, provided your app doesn't need to use non-collapsible messages. However, if you use collapsible messages, remember that FCM only allows a maximum of four different collapse keys to be used by the FCM connection server per registration token at any given time. You must not exceed this number, or it could cause unpredictable consequences.
| Use scenario | How to send | |
|---|---|---|
| Non-collapsible | Every message is important to the client app and needs to be delivered. | Except for notification messages, all messages are non-collapsible by default. |
| Collapsible | When there is a newer message that renders an older, related message irrelevant to the client app, FCM replaces the older message. For example: send-to-sync, or outdated notification messages. | Set the collapse_key parameter.
|
Setting the priority of a message
You have two options for assigning delivery priority to downstream messages: normal and high priority. Delivery of normal and high priority messages works like this:
- Normal priority. This is the default priority for data messages. Normal priority messages won't open network connections on a sleeping device, and their delivery may be delayed to conserve the battery. For less time-sensitive messages, such as notifications of new email or other data to sync, choose normal delivery priority.
- High priority. This is the default priority for notification messages. FCM attempts to deliver high priority messages immediately, allowing the FCM service to wake a sleeping device when possible and open a network connection to your app server. Apps with instant messaging, chat, or voice call alerts, for example, generally need to open a network connection and make sure FCM delivers the message to the device without delay. Set high priority if the message is time-critical and requires the user's immediate interaction, but beware that setting your messages to high priority contributes more to battery drain compared with normal priority messages.
Valid values are normal and high. For more details,
see the server reference for
HTTP or XMPP.
For iOS client apps, normal and high priority are analogous to APNs priority levels 5 and 10. For full details on iOS-specific behavior, see the APNs documentation. For details on Android-specific behavior, see Optimizing for Doze and App Standby.
Here is an example of a normal priority message to notify a magazine subscriber that new content is available to download:
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"priority" : "normal",
"notification" : {
"body" : "This week's edition is now available.",
"title" : "NewsMagazine.com",
"icon" : "new"
},
"data" : {
"volume" : "3.21.15",
"contents" : "http://www.news-magazine.com/world-week/21659772"
}
}
Setting the lifespan of a message
FCM usually delivers messages immediately after they are sent. However, this might not always be possible. For example, if the platform is Android, the device could be turned off, offline, or otherwise unavailable. FCM might intentionally delay messages to prevent an app from consuming excessive resources and negatively affecting battery life.
When this happens, FCM stores the message and delivers it as soon as it's feasible. While this is fine in most cases, there are some apps for which a late message might as well never be delivered. For example, if the message is an incoming call or video chat notification, it is meaningful only for a short period of time before the call is terminated. Or if the message is an invitation to an event, it is useless if received after the event has ended.
You can use the time_to_live parameter, supported in both
HTTP and
XMPP requests,
to specify the maximum lifespan of a message.
The value of this parameter must be a duration from 0 to 2,419,200 seconds (28
days), and it corresponds to the maximum period of time for which FCM
stores and attempts to deliver the message. Requests that don't contain this
field default to the maximum period of four weeks.
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
never throttles messages with a time_to_live (TTL) value of 0 seconds.
In other words, FCM guarantees best effort for messages that must be delivered
"now or never." Keep in mind that a time_to_live 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 JSON-formatted request that includes TTL:
{
"collapse_key" : "demo",
"to" : "xyz",
"data" : {
"key1" : "value1",
"key2" : "value2"
},
"time_to_live" : 3
}
Receiving messages from multiple senders
FCM allows multiple parties to send messages to the same client app. For example, suppose the client app is an article aggregator with multiple contributors, and each of them should be able to send a message when they publish a new article. This message might contain a URL so that the client app can download the article. Instead of having to centralize all sending activity in one location, FCM gives you the ability to let each of these contributors send its own messages.
To make this possible, make sure each sender generates its own sender ID. See the client documentation for your platform for information on on how to obtain the FCM sender ID. When requesting registration, the client app fetches the token multiple times, each time with a different sender ID in audience field.
Finally, share the registration token with the corresponding app servers (to complete the FCM registration client/server handshake), and they'll be able to send messages to the client app using their own authentication keys.
Note that there is limit of 100 multiple senders.
Lifetime of a message
When an app server posts a message to FCM and receives a message ID back, it does not mean that the message was already delivered to the device. Rather, it means that it was accepted for delivery. What happens to the message after it is accepted depends on many factors.
In the best-case scenario, if the device is connected to FCM, the screen is on and there are no throttling restrictions, the message is delivered right away.
If the device is connected but in doze mode, a low priority message is stored
by FCM until the device is out of doze mode. And
that's where the collapse_key flag plays a role: if there is already
a message with the same collapse key (and registration token) stored and waiting for
delivery, the old message is discarded and the new message takes its place
(that is, the old message is collapsed by the new one). However, if the collapse
key is not set, both the new and old messages are stored for future delivery.
If the device is not connected to FCM, the message is stored until a
connection is established (again respecting the collapse key rules). When a connection
is established, FCM delivers all pending messages to the device.
If the device never gets connected again
(for instance, if it was factory reset), the message eventually times out and
is discarded from FCM storage. The default timeout is four weeks, unless the
time_to_live flag is set.
If the device has not 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 receives the onDeletedMessages() callback. The app can then handle the situation properly, typically by requesting a full sync from the app server.
Finally, when FCM attempts to deliver a message to the device and the
app was uninstalled, 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.
Credentials
Depending on which FCM features you implement, you may need the following credentials from your Firebase project:
| Sender ID | A unique numerical value created when you create your Firebase project, available in the Cloud Messaging tab of the Firebase console Settings pane. The sender ID is used to identify each app server that can send messages to the client app. |
| Server key | A server key that authorizes your app server for access to Google services, including sending messages via Firebase Cloud Messaging. You obtain the server key when you create your Firebase project. You can view it in the Cloud Messaging tab of the Firebase console Settings pane. Important: Do not include the server key anywhere in your client code. Also, make sure to use only server keys to authorize your app server. Android, iOS, and browser keys are rejected by FCM. |
| Registration token | An ID generated by the FCM SDK for each client app instance. Required for single device and device group messaging. Note that registration tokens must be kept secret. |

