Firebase Cloud Messaging delivery and token lifecycle
FCM is a best-effort wake-up/delivery channel, not your business database. Messages can be delayed, collapsed, duplicated, or unavailable; the app must reconcile with server truth.
Message styles
- Notification message: SDK/system can display it when the app is backgrounded; handling differs by app state.
- Data message: app code interprets the payload when delivered; gives control but not unlimited execution time.
- Combined: notification plus data; behavior still varies between foreground/background.
Do not put secrets or full sensitive records in the payload. Send a type, stable entity/version ID, and fetch authorized data over TLS.
class AppMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
tokenRepository.recordPendingToken(token)
tokenSyncScheduler.enqueue()
}
override fun onMessageReceived(message: RemoteMessage) {
val eventId = message.data["eventId"] ?: return
val orderId = message.data["orderId"] ?: return
if (!safeId.matches(orderId)) return
eventStore.recordIfNew(eventId, orderId)
notificationPublisher.publishOrderUpdate(orderId)
}
}
onMessageReceived has a short processing window. Post a notification promptly. For longer durable processing, persist minimal intent and schedule WorkManager; do not start an unrestricted background service.
Token lifecycle is many-to-many
A registration token identifies an app installation instance, not a person forever. It can rotate. One user may have several devices; a device may change users.
Server model should associate token with installation, platform, current user/session binding, update time, and notification preferences. On sign-out, detach or invalidate that user binding. Delete invalid/unregistered tokens reported by sends.
Priority
Normal priority may be delayed in Doze. High priority is for time-sensitive, user-visible content and should normally lead to a notification. Consistently using high priority without visible outcomes can lead to deprioritization.
High priority does not mean guaranteed or exactly-once. Critical alarms, financial correctness, and message history must not depend solely on push arrival.
Topics
Topics are suitable for broad public segments such as weather alerts for a region, not private per-user authorization. Anyone able to subscribe a client must not gain access to confidential payloads. Enforce targeting and data access on trusted servers.
Delivery-safe architecture
Server commits event + outbox
↓
Push says “entity 42 changed to version 7”
↓
App deduplicates event ID
↓
App fetches authorized current state
↓
Room updates; UI and notification derive from truth
Sending belongs in a trusted environment using the HTTP v1 API/Admin SDK and scoped service credentials. Embedding a server key or service-account credential in an APK exposes it.
Sources
- Receive messages on Android
- Set and manage message priority
- Manage registration tokens
- Message types
Exercise
Design chat push handling for duplicate delivery, token rotation, multiple devices, muted conversations, signed-out state, Doze, and a process killed immediately after receiving the message.