About FCM Messages

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.

Notification messages contain a predefined set of user-visible keys. Data messages, by contrast, contain only 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.
  1. In a trusted environment such as Cloud Functions or your app server, use the Admin SDK or the HTTP and XMPP APIs: Set the notification key. May have optional data payload. Always collapsible.
  2. Use the Notifications composer: Enter the Message Text, Title, etc., and send. Add optional data payload by providing Custom data. Always collapsible.
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 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 programmatically 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 iOS
  • onMessageReceived() on Android. The notification key 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 programmatically 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 enable this feature, make sure you have each sender's sender ID. When requesting registration, the client app fetches the token multiple times, each time with a different sender ID in audience field, using the token retrieval method for the given platform:

Finally, share the registration token with the corresponding senders, 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.

To get more insight into the delivery of a message:

  • For Android: If you'd like to be notified when the application successfully receieves a message, you can use delivery_receipt_requested functionality following the guidelines. This requires you to setup an XMPP server.
  • For Android, iOS and Web: You can use InstanceID APIs to check the most recent date that the device you're targeting through the FCM registration token has established a connection with FCM.

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.


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.

Send feedback about...

Need help? Visit our support page.