skip to content

In a React Native app, what is a push device token, and which provider issues it on iOS and on Android?

level: juniorimportance: must knowfreq 60%

answer

  1. an address for one app install
  2. iOS: Apple Push Notification service
  3. Android: Firebase Cloud Messaging
  4. opaque string, can change
  5. the backend stores it per install

basics

~20 s

A device token is an opaque address the push provider issues for one app installation. On iOS it comes from APNs, on Android from FCM; the app sends it to its backend, which uses it to target that install.

solid answer

~40 s

A **device push token** is an opaque string that identifies one installation of the app to a push provider, so a server can address a notification to that install. On iOS the provider is **APNs** (Apple Push Notification service); on Android it is **FCM** (Firebase Cloud Messaging), which needs Firebase configured in the app (a `google-services.json`). React Native core offers no current push API (its iOS-only `PushNotificationIOS` is deprecated): you get the token from a library, `getDevicePushTokenAsync()` in `expo-notifications` or `getToken()` in React Native Firebase messaging, then send it to your backend together with the signed-in user. The token is **not permanent**, so the app must report it again when it changes. Expo also offers an **Expo push token** (`ExponentPushToken[...]`) that its push service relays to APNs or FCM.

go deeper

for a junior

Recall that iOS tokens come from APNs, Android tokens from FCM, and that the app sends its token to its own backend.

for a middle

Explain which library call returns which token type in Expo and React Native Firebase, and how FCM on iOS relays through APNs.

for a senior

Show you design for token change: refresh listeners, per-install storage and pruning tokens the provider rejects.

for a principal

Weigh talking to APNs and FCM directly against a relay such as Expo's push service, in terms of credentials ownership and vendor coupling.

## What the token is for A push notification travels from **your server** to a **push provider**, and from the provider to the device. Your server cannot address a phone directly; it needs an identifier the provider understands. That identifier is the **device push token**: - it identifies **one installation of one app** on one device, not a user and not a phone; - it is **opaque**: the app should store and send it as-is, never parse it; - it is **issued by the provider** through the operating system, not generated by the app. In a pharmacy app that sends "your prescription is ready" messages, the backend keeps a table of tokens per user, one row per installed device, and sends each order-status push to every row for that user. ## Which provider on each platform | | iOS | Android | |---|---|---| | Provider | **APNs** (Apple Push Notification service) | **FCM** (Firebase Cloud Messaging) | | Token issued via | the OS registering the app for remote notifications | Google Play services on the device | | App-side prerequisite | push capability (the `aps-environment` entitlement) in the signed build | Firebase config, `google-services.json` | | Server needs | Apple push credentials for the app | Firebase credentials for the project | Details worth knowing: 1. **React Native core is not the place to get tokens.** Core's iOS-only `PushNotificationIOS` is deprecated: it warns that it was extracted from core and will be removed. Tokens come from `expo-notifications` or `@react-native-firebase/messaging`. 2. With **React Native Firebase**, `getToken(getMessaging())` returns an **FCM token on both platforms**. On iOS, FCM still delivers through APNs underneath: the FCM SDK needs the APNs token first and maps its FCM token onto it. 3. With **expo-notifications**, `getDevicePushTokenAsync()` returns `{ type: 'ios', data }` with the raw APNs token on iOS and `{ type: 'android', data }` with the FCM token on Android. 4. **Expo push tokens** are a third option: `getExpoPushTokenAsync()` returns `ExponentPushToken[...]`, an address in Expo's push service, which then talks to APNs or FCM for you. ## The token's lifecycle A token is not a stable device ID. It can change when: - the app is reinstalled or its data is cleared; - the provider rotates it; - the app is restored onto a new device. So the app must: - fetch the token on startup (cheap, usually cached by the library); - **listen for changes**: `onTokenRefresh` in React Native Firebase, `addPushTokenListener` in `expo-notifications`; - send the current token to the backend, tied to the signed-in user, whenever it changes or the user signs in. The backend, in turn, deletes tokens the provider reports as no longer registered. ## What the token is not - **Not a secret credential.** Someone holding a token still needs your server's provider credentials to push to it, but you should keep tokens out of logs and analytics anyway, since they identify an install. - **Not a permission.** Getting a token and being allowed to show alerts are separate steps. On iOS the notification permission decides whether alerts are shown; on Android 13+ the `POST_NOTIFICATIONS` runtime permission does. - **Not portable across providers.** An APNs token is useless to FCM's API and vice versa, and an Expo push token only works with Expo's push service. ## Where the code lives in a React Native app Token handling is start-up plumbing, not screen logic: - fetch the token once the user is signed in, because the backend needs to know whose device it is; - register the refresh listener in a module or root component that lives for the whole session; - send token, platform and provider type together, since the backend must know whether a string is an APNs, FCM or Expo token before it can use it. In the pharmacy app this means a small `registerDevice` step after sign-in, reused on every launch, rather than code inside the order-status screen that may never be opened. ## How this is asked Junior interviews usually want three facts: tokens come from APNs on iOS and FCM on Android, the app must send them to its own backend, and they change over time. A good answer adds which library call produces the token in the project's stack and where the refresh listener lives.

  • Does a React Native Firebase app on iOS talk to FCM or APNs?
    Both. Your server sends to FCM with the FCM token from `getToken()`, and FCM forwards to APNs, which delivers to the device. That is why the iOS app still needs the push capability and Apple credentials uploaded to Firebase, and why the FCM SDK on iOS needs an APNs token before it can issue an FCM token.
  • Why store tokens per installation rather than one token per user?
    A user can have the app on a phone and a tablet, each with its own token. Storing one token per user means the last device to register silently steals all notifications. A per-installation row, updated in place when the token changes, lets the backend send an order update to every device and delete only the one that becomes invalid.

A device token is like a PO box number the post office assigns to one household's mailbox: senders need it to reach you, it is meaningless to a different postal service, and if you move the box you must tell everyone the new number.

saying these in an interview costs you the question

  • The device token identifies the user across all their devices
  • Core PushNotificationIOS is the current cross-platform way to get tokens
  • A device token never changes once issued
  • An APNs token can be sent through FCM's API unchanged
  • Getting a token means the user has allowed notifications