When a notification arrives while an app is open, the app can often receive the event and decide what to do with it. When the app is closed, that responsibility changes. The operating system, notification provider, device settings, and payload all influence whether a notification is delivered, displayed, delayed, or discarded.
This distinction explains many apparently inconsistent results. A successful server request does not necessarily mean a user saw a notification. It usually means the notification service accepted the request for processing. Delivery and display still depend on device state, permissions, registration details, operating-system rules, and the notification’s contents.
This guide explains the main causes of disappearing notifications and provides a practical way to diagnose them across mobile and web applications.
First, separate delivery from app processing
A closed app cannot be relied on to run arbitrary application code at the moment a push message arrives. In many cases, the operating system receives the push and displays a notification itself. In other cases, it may deliver data to the application only when background execution is permitted and the payload is suitable for that delivery mode.
That creates two different notification paths:
- Display path: the operating system receives a notification payload and presents it without needing the application to launch first.
- Application path: the application receives data, processes it, and may create or update a local notification.
The display path is generally the safer choice when the requirement is simply to show an alert while the app is closed. The application path is more flexible, but it is subject to background execution limits, platform-specific behaviour, battery policies, and payload rules.
A common implementation mistake is to send data that the app must process, then expect the operating system to display it automatically. That may work while the app is in the foreground because application code is running, but fail when the app is closed.
Permissions and notification settings
A device may be correctly registered and reachable while notifications are still blocked. Users can deny permission during onboarding, disable notifications later, turn off sounds or badges, suppress lock-screen alerts, or enable a focus, do-not-disturb, or battery-saving mode.
Check settings at several levels:
- Application permission: has the user granted notification permission?
- Notification category or channel: is the relevant category enabled?
- Device mode: could focus, do-not-disturb, bedtime, or battery-saving rules be suppressing presentation?
- Browser permission: for Web Push, has the site been allowed to notify?
- System presentation settings: are alerts allowed on the lock screen, notification centre, or desktop?
Permission state should be treated as changeable. An application should not assume that a previous approval remains unchanged. Where the platform allows it, refresh permission state at an appropriate point and provide a clear route to settings rather than repeatedly requesting permission without context.
Also distinguish delivery from visibility. A notification might be delivered but hidden from the user’s preferred surface, grouped with other notifications, muted, or removed by an automatic system policy.
Payload design matters when the app is closed
The payload determines whether the operating system can present a notification without application code. For a visible alert, include the fields required by the relevant platform and ensure the target device can interpret them. At a minimum, the user-facing content should have a meaningful title and body.
Avoid making a visible alert depend on a background callback that may not run. If the app must fetch additional content, make the notification useful on its own and treat the follow-up fetch as an enhancement rather than the only way to create the alert.
Payloads should also be concise and purposeful. Large payloads, unsupported fields, invalid values, or incompatible platform options can cause rejection, alteration, or inconsistent behaviour. Platform-specific payload details vary, so validate them against the current documentation for each target platform.
Be particularly careful with messages described as silent, background-only, or data-only. These are useful for synchronisation and application logic, but they are not the same as a visible notification. If the requirement is “show this while the app is closed”, explicitly test a display-capable payload rather than assuming a background event will become visible.
Closed is not one device state
Teams often use “closed” to describe several different conditions:
- The app is in the background but still resident in memory.
- The user has swiped the app away from the recent-apps view.
- The application has been force-stopped through device settings.
- The operating system has terminated the app to reclaim resources.
- The device is locked, offline, roaming, or in a restricted power state.
These states do not have identical rules. A backgrounded app may receive an event that a force-stopped app cannot process. A device without a network connection may receive the notification later, depending on provider and operating-system handling. A notification can also be queued, collapsed, delayed, or replaced according to platform behaviour and request options.
Test each state deliberately. Do not describe a result as “works when closed” unless you have specified whether the app was backgrounded, terminated by the system, or force-stopped by the user.
Registration and token lifecycle problems
Push delivery depends on a valid registration that represents the current application installation and provider environment. Tokens can change after reinstallations, permission changes, application updates, device restores, or provider-side events. A device may also have separate registrations for development and production environments.
The client should register or refresh its device token according to the platform lifecycle, then send the current value to your server or notification service. Your server should avoid treating an old token as permanently valid. When delivery errors indicate an invalid or expired registration, remove or update it according to your retention policy.
HoneyNotify client SDKs cover device registration, identity, token lifecycle, payload handling, and lifecycle events across iOS, Android, and Web Push. Use those lifecycle events to keep registration state current rather than registering once and assuming it never changes.
Imported identifiers require additional care. Imported OneSignal subscription IDs can remain as device IDs when matching provider tokens later register. However, token rotation or another provider environment can prevent matching. If an imported device does not receive notifications, compare the current provider token, environment, application identity, and import mapping rather than relying on the historical identifier alone.
Server-side request checks
A server-side send must be accepted by the notification service before delivery can begin. With HoneyNotify, sends use POST /v1/notifications with a Bearer API key and an Idempotency-Key. A notification requires a title, body, and target. Targets can address a device, user, tag, segment, or all enabled devices.
Check the request in this order:
- Confirm that the API key belongs to the intended environment and has the required access.
- Confirm that the target resolves to at least one enabled, current registration.
- Confirm that title and body are present and contain the intended content.
- Use a unique Idempotency-Key for each logical send, and reuse the same key only when safely retrying that same request.
- Record the service response and correlate it with your own notification identifier.
Idempotency prevents a network retry from unintentionally creating duplicate logical sends, but it does not make an invalid target valid or guarantee that a user sees the result. Treat request acceptance, provider delivery, device receipt, and user presentation as separate stages in your observability model.
A practical debugging sequence
Start with one known test device and one simple visible notification. Avoid segments, complex conditional targeting, rich media, and background-only data until the basic path works.
Then verify the following:
- The device has a current registration and belongs to the intended application environment.
- The user or device is enabled and resolves from the selected target.
- Notification permission and relevant system settings allow alerts.
- The app has a valid notification channel or category where the platform requires one.
- The payload contains a visible title and body rather than only background data.
- The server received a successful response for the intended request.
- The device was online, or you waited long enough to test delayed delivery.
- The app was tested in foreground, background, system-terminated, and force-stopped states separately.
- Client and server logs show registration, token refresh, send, receipt, and presentation events where available.
If a visible payload works while the app is closed but a data-only payload does not, the issue is probably the delivery mode or background execution assumptions. If neither works, investigate permission, targeting, registration, environment, and device settings before changing application callbacks.
Common mistakes
Assuming an HTTP success means a notification was seen
A successful API response normally confirms request handling, not user presentation. Keep separate records for request acceptance and downstream delivery outcomes.
Building the alert only in application code
This makes the notification depend on background execution. Use a platform-supported visible notification payload when the operating system should display the alert while the app is closed.
Keeping stale registrations indefinitely
Old tokens create misleading targeting results and can make a broad send appear unreliable. Refresh registrations and remove invalid ones.
Testing only one app state
Foreground testing can hide payload and background-execution problems. Include system termination and force-stop tests, and document the exact steps used.
Mixing environments
A development registration is not automatically interchangeable with a production registration. Check application identifiers, provider environments, credentials, and current tokens together.
Conclusion
Notifications do not necessarily disappear because the server failed. More often, the app is being asked to perform work that the operating system will not run while it is closed, or the device registration, permission state, payload, target, or environment is incorrect.
Design the closed-app path around an operating-system-displayable notification, keep tokens and permissions current, and instrument each stage from request acceptance to presentation. That approach turns an intermittent-looking problem into a sequence of verifiable checks.
