Firebase Cloud Messaging (FCM) is a cross-platform push notification and message delivery service from Google, designed for mobile and web applications. FCM ensures reliable data transfer between the server and client devices without the need to maintain a persistent network connection. According to Firebase Documentation, 2026, more than 300 billion messages pass through the FCM infrastructure daily worldwide. The service supports both automatically displayed notifications and data messages for background data transfer.
Key Takeaways
Firebase Cloud Messaging is a Google cloud service that delivers push notifications and data messages between the application server and client devices. The service replaced the legacy Google Cloud Messaging (GCM) and became the standard solution for push delivery in the Firebase ecosystem. FCM supports Android, iOS, Web and Unity, providing a unified sending interface regardless of the target platform.
The service provides several message delivery mechanisms, each solving a specific task. Notification messages are displayed automatically by the system upon receipt — the developer does not need to write code to show the notification. Data messages transmit arbitrary payload as key-value pairs and are processed inside the application. Combined messages contain both visible and hidden parts for maximum flexibility.
Implementing your own push server requires maintaining a constant TCP connection with each device, which is inefficient and insecure. FCM uses Google’s unified infrastructure that maintains connections with billions of devices simultaneously. The service automatically manages delivery retries, message queues and load balancing, freeing the developer from having to solve these tasks independently.
FCM architecture consists of three key components: the provider server (your backend), the Firebase Cloud Messaging server and the client application on the device. When the server sends a message, it first enters the FCM infrastructure, which routes it to the target device. If the device is offline, FCM stores the message in a queue and delivers it when the connection is restored.
On first launch, the application calls the Firebase SDK, which registers the device with the FCM service and receives a unique Registration Token. This token is a string about 150 characters long and identifies a specific application instance on a specific device. The token may change when the application is reinstalled, data is cleared or restored from backup — the developer must handle token updates through the onNewToken delegate.
When the server sends a request through the FCM API, the message goes through several stages. Receipt and validation — FCM checks the request validity and verifies the target device exists. Queue — if the device is unavailable, the message enters a storage queue. Routing — FCM determines the optimal delivery channel (WiFi or cellular data). Delivery — the system transmits the message to the target application. After successful delivery, FCM returns a message ID to the server.
Firebase Cloud Messaging supports three message types, each with its own processing characteristics on the client side. Notification messages are handled by the system service Google Play Services on Android and APNs on iOS, and are automatically displayed as push banners. Data messages are delivered directly to the application and processed through the onMessageReceived callback in Android and application(_:didReceiveRemoteNotification:) in iOS.
A notification message contains predefined fields: title, body, image URL and notification sound. The system automatically creates and displays the notification in the system tray, even if the application is in the background or terminated. The user sees a standard banner with a title and text, and when tapped, the application opens with the data passed in the payload. If the application is active, the notification message can be intercepted and processed in code.
A data message is a custom set of key-value pairs without predefined fields. The payload is not processed by the system automatically — the application receives raw data and can interpret it arbitrarily. Data messages are used for background data synchronization, local cache updates, sync triggers, or sending commands without displaying a notification. On Android, data messages are always delivered, even if the application is terminated or in the background.
FCM allows sending a message that contains both a notification part (for display) and a data part (for processing). The combined payload includes both predefined notification fields and arbitrary data keys. The system displays the notification from the notification part, while the data part is passed to the application’s intent extras when opened. This is convenient for scenarios where you need to show the user a notification and simultaneously pass context for navigating to a specific screen.
| Type | Auto-display | Background processing | Example |
|---|---|---|---|
| Notification | Yes, by system | Automatically, without code | Welcome push notification |
| Data | No | Via application callback | Background data sync |
| Combined | Yes, notification part | Data part on open | Notification + order link |
Integrating FCM in Android starts with connecting the Firebase SDK through the build.gradle file at the application level. After adding the dependencies and the google-services.json file, the application automatically receives a Registration Token, which is passed through the FirebaseMessagingService callback. To receive notifications, you need to create a service extending FirebaseMessagingService and register it in AndroidManifest.xml.
After connecting the Firebase SDK, the device token is generated automatically without additional code. The token is available via FirebaseMessaging.getInstance().token, which returns a Task<String>. To track token updates, override the onNewToken method in the service. The token must be sent to the provider server so that the server can send push notifications to this device.
class MyFirebaseMessagingService :
FirebaseMessagingService() {
override fun onNewToken(token: String) {
sendTokenToServer(token)
}
override fun onMessageReceived(
message: RemoteMessage
) {
val data = message.data
val title = "New message"
val body = data["body"] ?: ""
showNotification(title, body)
}
}
The service for receiving FCM messages must be registered in AndroidManifest.xml with the appropriate intent-filter. Add a service tag with the INTERNET permission and the specified action. Without service registration, messages will not be delivered to the application in the background. Displaying notifications on Android 13+ requires the runtime permission POST_NOTIFICATIONS.
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name=
"android.permission.POST_NOTIFICATIONS" />
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name=
"com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Integrating FCM in iOS requires configuration both on the Apple Push Notification Service (APNs) side and in the Firebase Console. Unlike Android, where FCM manages the connection directly, on iOS FCM uses APNs as the transport layer. The application registers for push notifications via UIApplication.shared.registerForRemoteNotifications, and the Firebase SDK intercepts the received device token and links it to the FCM Registration Token.
For FCM to work on iOS, you need to upload an APNs key or certificate in the Firebase Console. The APNs key is a modern authentication method without certificates (recommended by Apple). The key is created in the Apple Developer Portal under the Keys section and uploaded to the Cloud Messaging settings in the Firebase Console. After APNs configuration, the application requests notification permission via UNUserNotificationCenter and registers via APNs.
import Firebase
import UserNotifications
class AppDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge])
application.registerForRemoteNotifications()
return true
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken
deviceToken: Data
) {
Messaging.messaging()
.apnsToken = deviceToken
}
}
To handle received notifications, implement the UNUserNotificationCenter delegate. The willPresent method is called when a notification is received while the application is active — here you can show a custom in-app notification or ignore the system banner. The didReceive method is called when the user taps the notification — here you navigate to the corresponding screen. For data messages, the MessagingDelegate is used, which receives the payload when an FCM message is received in the background.
Server-side sending of FCM messages is performed through the HTTP v1 API of Firebase Cloud Messaging or the legacy Firebase Cloud Messaging API. The HTTP v1 API is the recommended method, uses OAuth 2.0 authentication via a Service Account and supports all modern FCM features, including delivery analytics and A/B testing of notifications. The request is sent via POST method to the endpoint https://fcm.googleapis.com/v1/projects/{project_id}/messages:send.
The request body contains a JSON object with message information: target (token, topic or condition), notification (for display) and data (custom payload). Authentication is done via a Service Account JSON key loaded into the server environment variables. The access token is generated using the google-auth-library. Google recommends using the Firebase Admin SDK for automatic authentication management and retries.
const admin = require("firebase-admin")
const serviceAccount = require("./serviceAccountKey.json")
admin.initializeApp({ credential: admin.credential.cert(serviceAccount) })
const message = {
token: "device_registration_token",
notification: { title: "20% discount", body: "On all services today" },
data: { screen: "promo", promoId: "324" },
android: { priority: "high" },
apns: { payload: { aps: { sound: "default" } } }
}
admin.messaging().send(message)
.then(response => {
console.log("Successfully sent:", response)
})
.catch(error => {
console.log("Send error:", error)
})
For sending notifications to a group of users, FCM supports topic subscriptions. A topic is a named channel that the client application subscribes to via FirebaseMessaging.getInstance().subscribeToTopic(). The server can send a message to a topic and it will be delivered to all subscribed devices. Topics are suitable for news feeds, promotional notifications and event-based pushes. For more precise segmentation, conditions based on multiple topics with logical operators are used.
Frequently Asked Questions
FCM works on Android through Google’s own infrastructure, while on iOS it uses APNs as the transport protocol. FCM provides a unified API for both platforms, automatic offline message storage and delivery analytics, which are not available in pure APNs.
Yes, through the Firebase Console in the Cloud Messaging section, you can manually send notifications to selected devices, topics or audience segments. This feature is suitable for testing and one-off broadcasts, but does not replace server integration for production applications.
Subscribe to token updates via onNewToken in FirebaseMessagingService (Android) or MessagingDelegate (iOS). When the token changes, send the new token to the server and remove the old one. The server should update the database and stop attempting to send to the outdated token.
FCM stores the message in a queue for up to 28 days and delivers it when the connection is restored. For notification messages, only the last message for each collapse group is collapsed. Data messages are stored separately and delivered in sending order without collapsing.
FCM is completely free with no limits on the number of messages. FCM usage is not charged under either the Spark plan or the Blaze plan. There are only payload size limits: up to 4 KB for notification messages and up to 2 KB for data messages.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also