Push notifications are often an app's most important channel to its users: an appointment reminder, an order status update, a login code, a promotion. When they stop arriving, nobody notices right away — the app doesn't crash, the store console raises no alarm, and the backend reports that sending "went through". The first sign is often a drop in orders or a customer asking why they never got a reminder.
The good news: the list of possible causes is finite, and most of them can be diagnosed in a day or two. This article explains how to find where the problem is and how to fix it, step by step, starting with the most common cases.
How push notification delivery works
To find the cause, you need to know how many hands a single notification passes through:
- The app registers with the push service on startup and receives a device token.
- The app sends the token to your backend, which stores it.
- When a notification needs to go out, the backend sends it to the push service: Firebase Cloud Messaging (FCM) for Android and Apple Push Notification service (APNs) for iOS. iOS messages often go through FCM too, which forwards them to APNs.
- The push service delivers the message to the device.
- The device's operating system decides whether to show it — based on user permission, notification channels, battery saving and Focus modes.
The problem can sit at any of these stages. That's why, before anyone starts changing code, it's worth establishing who is affected.
Step 1: narrow down the scope
A few questions narrow the search more than an hour of reading code:
- All users or only some? If nobody gets notifications, the problem is almost certainly in the backend or the push service configuration.
- One platform or both? If Android works and iOS doesn't (or the other way round), look at that platform's configuration: APNs certificates, keys in Firebase, permissions.
- Since when? Match the date against app releases, server changes and deadlines announced by Google and Apple.
- New or existing users? If only people who installed the app recently are affected, the cause is usually the permission prompt or token registration.
- Specific phone brands? Complaints only from Xiaomi or Huawei users point to battery optimisation or missing Google services.
Next, look at the backend logs with push service responses. FCM and APNs return a specific error code for every send — UNREGISTERED, THIRD_PARTY_AUTH_ERROR, BadDeviceToken, ExpiredProviderToken. If your backend doesn't log these responses, fix that first — without them you're diagnosing blind.
The most common causes
Symptom Likely cause How to confirm Nobody gets notifications, starting on a specific day sending through the old FCM API, an expired key or a server change backend logs: authorisation errors on every send Android works, iOS doesn't expired APNs certificate, missing APNs key in Firebase, wrong environmentTHIRD_PARTY_AUTH_ERROR from FCM or APNs errors
Only new Android users miss out
no notification permission request (Android 13+)
app settings on a fresh install
Notifications arrive with long delays
battery optimisation, low message priority
test on several phone models
Users of one brand don't get them
aggressive battery management or no Google services (Huawei)
complaints broken down by manufacturer
Fewer and fewer delivered, no clear start date
stale tokens in the database
share of UNREGISTERED errors over time
Problem started after the app was transferred
keys and Firebase project left on the old account
Apple Developer and Firebase configuration
The details of each cause follow below.
The legacy Firebase Cloud Messaging API
This is the most common cause in apps nobody has worked on for a few years. Google deprecated the older FCM sending APIs (the legacy HTTP and XMPP APIs, authorised with a server key) in June 2023 and shut them down during 2024. A backend that still sends notifications "the old way" now gets errors — and if nobody logs FCM responses, it looks as if sending works.
The fix is to move to the FCM HTTP v1 API: instead of a static server key, the backend uses a Google service account and short-lived OAuth 2.0 tokens, and the message format is slightly different. The change is backend-only — the app in the store doesn't need an update. For a typical backend, it's one to three days of work including testing.
If you send through an intermediary — OneSignal, Azure Notification Hubs, Expo — check that its dashboard has FCM v1 credentials configured. These providers required the migration too.
APNs certificates and keys (iOS)
Apple offers two ways to authenticate with APNs:
- Certificate (.p12) — valid for one year. Once it expires, iOS notifications stop overnight while Android keeps working. In apps we take over, this is still a common scenario: the certificate used to be renewed by someone who no longer works with the company.
- Key (.p8) — doesn't expire and works for all apps in the account. It can, however, be revoked, for example during an account clean-up.
If iOS goes through FCM, the certificate or key is uploaded in the Firebase project settings. An expired one shows up there as THIRD_PARTY_AUTH_ERROR. The fix: generate a .p8 key, upload it to Firebase (or your own backend) and remove the old certificate from the configuration. While you're at it, write down who has access to the Apple Developer account — a frequent problem when your developer disappears.
Other iOS-side errors:
- Mixed-up environments. Development builds get sandbox tokens, while TestFlight and App Store builds get production tokens. A token sent to the wrong environment fails with
BadDeviceToken. - The APNs JWT has to be refreshed — APNs rejects tokens older than an hour (
ExpiredProviderToken) and doesn't like a new one generated for every send. - An outdated certificate store on the server. In early 2025 Apple changed the certificate authority for APNs servers. A backend running on an old operating system or an old Java version may not trust the new certificate and fail to connect.
For testing, use the Push Notifications Console in the Apple Developer portal: it lets you send a test notification to a specific token and check its delivery log.
Notification permission on Android 13 and later
Since Android 13, notifications require user permission, just like on iOS. An app targeting Android 13 or later (target API 33+) has to request the POST_NOTIFICATIONS permission itself. If it doesn't, new users have notifications turned off and don't even know it.
This is a common side effect of forced updates. Google Play requires updates to target ever newer APIs — in 2026 that's API 36. Someone raises the target API so the app passes store review, doesn't add a permission request — and from that version on, new users stop getting notifications. Existing users usually keep their permission, so the problem grows slowly and is hard to tie to a specific release.
Check the notification channels too (since Android 8). A notification sent to a channel the app never created won't be shown. Users can also turn off a single channel, such as "Promotions", while leaving the others on.
Good practice is to ask for permission when it makes sense — for example after an order is placed ("Want us to notify you about delivery status?"), not on first launch. Refusals are most common on first launch, and you get few chances: iOS shows the system prompt only once, and Android stops showing it after two refusals. More on changes in new OS versions: app not working on new Android or iOS.
Device tokens: stale and never saved
A device token isn't permanent. It changes after the app is reinstalled, its data is cleared, the phone is restored from a backup — and sometimes for no obvious reason. FCM treats the token of a device that hasn't connected to the service for more than 270 days as expired.
Typical mistakes here:
- The app sends the token only on first registration, not after it's refreshed. The backend keeps sending to an old token that no longer works.
- The backend never removes stale tokens.
UNREGISTEREDorBadDeviceTokenresponses are ignored, the database grows, and sending statistics become less and less reliable. - The token is tied to an account rather than a device. A user with a phone and a tablet gets notifications on only one of them — or keeps getting another account's notifications after logging out.
Firebase recommends that the app send its current token with a timestamp on every launch (or at least once a month), and that the backend remove tokens that return errors or haven't been refreshed for a long time.
Battery saving and phones without Google services
Android lets manufacturers interfere with how apps run in the background. Xiaomi, Samsung, Oppo and Huawei all have their own mechanisms for putting apps to sleep, which can delay or block notifications — especially for apps that are rarely opened.
What you can do in the app and the backend:
- Send user-visible notifications with high priority — but only those. Android deprioritises apps that send high-priority messages and then don't show a notification.
- Use messages with a
notificationsection for regular notifications. Data-only messages require the app to wake up and build the notification itself — which is exactly what battery saving blocks. - On iOS, silent notifications (
content-available) are throttled by the system and don't reach an app the user has force-quit. Don't rely on them for anything that must arrive.
A separate case is Huawei phones without Google services (models sold from 2019–2020 onwards). FCM doesn't work on them. If this group matters to you, you need a Huawei Push Kit integration — or a deliberate decision that these users get information through another channel, such as SMS or email.
Problems after an app transfer or a change of vendor
When you transfer an app to another account or take it over from another company, push notifications break very often, because their configuration is spread across several places:
- the Firebase project may belong to the previous vendor's Google account — and with it you can lose access to sending and statistics,
- the APNs key is tied to a team in Apple Developer; after the app moves to another account, a new key has to be generated in the new team,
- the push service credentials sit in environment variables on a server nobody has access to.
That's why access to Firebase, APNs keys and the server configuration should be on the handover list every time you change vendors.
How to test without guessing
An order that quickly shows at which stage a notification gets lost:
- Send a test notification straight to a specific device's token — from the Firebase console (Android, and iOS via FCM) or from Apple's Push Notifications Console. If it arrives, the push service and the device are fine, and the problem is in the backend.
- Send the same from your backend and check the push service's response. An authorisation error points to keys and the API; a token error points to registration.
- Install the app from scratch on Android 13+ and on iOS. Check whether the app asks for permission and whether the token reaches the backend.
- Check the delivery reports. Firebase shows message delivery statistics (exportable to BigQuery); Apple shows a delivery log for a specific token.
Going forward, track the share of successful sends and the number of errors over time — the same way you monitor app crashes. A sudden spike in errors tells you something has changed before your customers do.
How long the fix takes
Cause What needs doing Rough time Legacy FCM API migrate the backend to FCM HTTP v1 1–3 days Expired APNs certificate .p8 key, configuration in Firebase or the backend a few hours No permission request on Android 13+ permission request, channels, new release 1–2 days + store review Stale tokens refresh in the app, clean-up in the backend 1–3 days Huawei without Google services Push Kit integration a few days, depending on the architectureThe time depends mainly on whether you have access to the code, the accounts and the server. If you first need to regain access to Firebase or the Apple Developer account, that step usually takes the longest.
Summary
Push notifications usually stop working for one of a handful of reasons: the legacy FCM API being shut down, an expired APNs certificate, no permission request after the target API was raised, stale tokens, or configuration left on the previous vendor's account. Start by narrowing down the scope and by reading the push service responses in your logs — in most cases that points to the cause without a long search.
If notifications in your app have stopped arriving and you don't know where to start, request a free app analysis — we'll check your sending configuration, permissions and account access. We provide ongoing care, including keys, certificates and adapting to new OS versions, as part of our mobile app maintenance service.