Last updated: 27/07/2026
The short answer
Push notifications look free and behave like a scarce resource. The platforms have spent the last few years making that explicit, and the rules are published, specific and testable — you do not need to be technical to hold a build to them. On Android, Android 13 (API level 33) and higher requires the POST_NOTIFICATIONS runtime permission, and Google states plainly that if a user installs your app on such a device, "your app's notifications are off by default". On iOS, Apple's own guidance is that the system prompts once: "The first time your app makes this authorization request, the system prompts the person to grant or deny the request and records that response. Subsequent authorization requests don't prompt the person."
That is the operating system's permission. It is not the same thing as consent to market to somebody. App Store Review Guideline 4.5.4 is explicit that push "should not be used for promotions or direct marketing purposes unless customers have explicitly opted in to receive them via consent language displayed in your app's UI, and you provide a method in your app for a user to opt out from receiving such messages". Two permissions, two different mechanisms, two different failure modes. The rest of this article is what each one requires and what it means for how your app is scoped.
Two permissions, not one
The single most useful distinction an owner can carry into a scoping meeting is this: technical permission to deliver and commercial consent to market are separate, and satisfying one does not satisfy the other. The operating system's permission is a switch — granted, denied, or in Apple's case provisionally granted — and it governs whether a message can reach the device at all. Commercial consent governs what you are allowed to put inside that message, and it is the one that shows up in app review and in data-protection conversations.
Apple writes the second requirement into review policy rather than into the API. Guideline 4.5.4 asks for consent language "displayed in your app's UI" and for an opt-out method inside the app — which means a settings screen with real toggles, not an unsubscribe link buried in an email. Google's policies attack a related failure from the other end: its Ads policy states that "Ads must not simulate or impersonate the user interface of any app feature, such as notifications or warning elements of an operating system", and the Deceptive Behavior policy repeats it: "Don't display ads that mimic system notifications or warnings, making them appear as a part of the device's OS." A fake-looking alert is a policy problem on both stores.
The practical consequence for a build: your app needs a notification preferences screen, and its categories must be decided during design rather than bolted on after launch.
What each platform actually requires
Here are the two platforms side by side, using only what Apple and Google publish on their own developer pages. The shape is similar; the details that will bite you are different.
| Question | Apple (iOS) | Google (Android) |
|---|---|---|
| Is explicit permission needed? | Yes. Apple: "Because a person might consider notification-based interactions disruptive, you must obtain permission to use them." | Yes, on Android 13 (API level 33) and higher — the POST_NOTIFICATIONS runtime permission, for "non-exempt (including Foreground Services (FGS)) notifications". |
| Default state for a new install | Not authorised until the person grants it. | "If a user installs your app on a device that runs Android 13 or higher, your app's notifications are off by default." |
| How many chances to ask? | One system prompt. "Subsequent authorization requests don't prompt the person." | App targeting Android 13+ has "complete control over when the permission dialog is displayed". App targeting 12L (API 32) or lower: if the user taps Don't allow "even just once", they are not prompted again until they reinstall the app or you update it to target Android 13+. |
| What happens on an OS upgrade? | Existing authorisation persists. | The system "automatically pre-grants the permission to all eligible apps when the user upgrades their device to Android 13 or higher" — eligible meaning the app has an existing notification channel and did not have notifications explicitly disabled. |
| Is there a soft / trial option? | Yes — provisional authorization. Notifications arrive quietly, appear only in notification centre history, and include Keep / Turn Off buttons. Status stays provisional until the person decides. | Not documented as an equivalent. The dialog is the dialog. |
| Are notifications grouped into user-controllable categories? | Notification settings are per app; check getNotificationSettings() before scheduling, because "People can change your app's authorization settings at any time". | Yes — notification channels, mandatory since Android 8.0 (API level 26). The UI "refers to notification channels as 'categories'". |
| Marketing content rules | Guideline 4.5.4: explicit in-app opt-in with consent language, plus an in-app opt-out. Push must not be required for the app to function. | Play policies prohibit ads that mimic system notifications or OS warnings. |
All rows quoted from developer.apple.com and developer.android.com. Where a platform publishes nothing on a point, the cell says so rather than guessing.
You usually get one prompt, so time it
The single highest-leverage design decision in this whole area is when the permission dialog appears, because on both platforms you effectively get one clean shot at it. Apple is unusually direct about this: "Make the request in a context that helps people understand why your app needs authorization… Sending the request in context provides a better experience than automatically requesting authorization on first launch, because people can see the purpose your apps notifications serve." Their worked example is a task-tracking app that asks after the person schedules their first task.
Google says the same in different words. If your app targets Android 13 or higher, "your app has complete control over when the permission dialog is displayed. Use this opportunity to explain to users why the app needs this permission, encouraging them to grant it." Note what that control is contingent on: targeting Android 13+. Target 12L or lower and the system shows the dialog for you — usually on app startup, and in single-activity apps "when the MainActivity starts" — the cold, contextless moment both platforms advise against.
Apple offers a genuine hedge here that most owners have never heard of: provisional authorization. Rather than asking up front, you can start sending quietly. Apple's description is precise — "The system delivers provisional notifications quietly — they don't interrupt the person with a sound or banner, or appear on the lock screen. Instead, they only appear in the notification center's history." Each one carries Keep and Turn Off buttons, and if the person presses Keep, the system asks them to choose Deliver Immediately or Deliver in Scheduled Summary. Apple notes that with provisional authorization "you can request authorization when your app first launches", because nobody is being interrupted. The trade-off is honest: your early notifications are quieter, and you are asking people to judge your notifications on the evidence rather than on a promise.
Channels and categories: the part owners forget
On Android, notification channels are not an optimisation — they are a hard requirement with a permanent consequence, and they are the reason "we'll decide the notification types later" is a bad plan. Google's rule is that since Android 8.0 (API level 26), "all notifications must be assigned to a channel", and if you target API 26 or higher and post one without a channel, "the notification doesn't appear and the system logs an error". Silently. In production.
The part that matters commercially is the next sentence: "After you create a notification channel, you can't change the notification behaviors. The user has complete control at that point. However, you can still change a channel's name and description." Your channel structure is close to permanent for every user who has already installed the app. If you ship one channel called "Notifications" that carries both delivery updates and promotional offers, then the day a customer mutes your promos they also mute their delivery updates — and you cannot split that channel retroactively for them. Get the categories right at design time: transactional, account and security, and marketing, at minimum, each as its own channel.
There is a second, quieter benefit. Channels let a user turn down the volume instead of turning you off entirely — and an app that offers only "all or nothing" tends to get nothing.
The delivery limits nobody mentions at kick-off
Push is a best-effort service, not a guaranteed message bus, and Apple documents that in unusually plain language. If your business plan depends on a notification arriving, the notification is the wrong channel for it — the table below is the reason why.
| Constraint | Published figure or rule | Source |
|---|---|---|
| Maximum payload, standard remote notification | 4 KB (4096 bytes) — APNs "refuses a notification" if the payload exceeds it | developer.apple.com |
| Maximum payload, VoIP notification | 5 KB (5120 bytes) | developer.apple.com |
| Storage of an undeliverable notification | "may store the notification for 30 days or less, depending on the date you specify in the apns-expiration header" | developer.apple.com |
| How many are stored per app | "APNs stores only one notification per bundle ID" — in most cases the latest, but "this behavior isn't always guaranteed" | developer.apple.com |
| Ordering | "APNs may reorder notifications you send to the same device token" | developer.apple.com |
| Lower-priority sends | apns-priority 5 and apns-priority 1 "might get grouped and delivered in bursts"; notifications "may also get throttled, saved in storage, and in some cases, not delivered" | developer.apple.com |
| Transport | HTTP/2 and TLS 1.2 or later; port 443, or port 2197 if you want to allow APNs through a firewall while blocking other HTTPS | developer.apple.com |
| Android channel requirement | Target API 26+ and post without a channel: "the notification doesn't appear and the system logs an error" | developer.android.com |
Every row quoted from the platform's own documentation. These are the constraints that turn "just send them a push" into a scoped feature.
Read the payload ceiling together with guideline 4.5.4's warning about sensitive information and a design principle falls out on its own: the notification is a pointer, not the content. It says something happened and deep-links into the app, where the person is authenticated and the real detail lives. That is also the pattern that survives a screen being read over somebody's shoulder on the MRT — a point we make at more length in our article on mobile app security and PDPA compliance.
Where Singapore law enters the picture
General information, not legal advice — take advice on your specific facts. What we can point to is what the statute itself says on its own page. Singapore's Personal Data Protection Act 2012 is, by its long title, "An Act to govern the collection, use and disclosure of personal data by organisations". Its arrangement of provisions puts consent in Part 4 — s13 Consent required, s14 Provision of consent, s15 Deemed consent, s15A Deemed consent by notification, s16 Withdrawal of consent, s17 Collection, use and disclosure without consent — and purpose in Division 2, with s18 Limitation of purpose and extent and s20 Notification of purpose. Part 6A covers Notification of Data Breaches.
Three practical implications follow from that structure, and each one is a build decision rather than a legal one.
- A push token rarely travels alone. To send a useful notification you hold a device token plus whatever you segmented on — order history, location, account status, behaviour in the app. The obligations in Part 4 attach to personal data, so the question your vendor should be able to answer is not "do we have permission to notify?" but "what did we tell the person we would use this data for, and does our targeting stay inside that?"
- Withdrawal has to actually work. The Act contains a section headed Withdrawal of consent (s16). Whatever the analysis of a specific message, an app that offers no way to withdraw is on the wrong side of both that provision and Apple's 4.5.4 opt-out requirement. Build the preferences screen.
- Do Not Call is about telephone numbers. Part 9 of the Act establishes the Do Not Call Registry, and its Division 3 is headed "Specified message to Singapore telephone number", with duties including s43 Duty to check register, s46 Consent and s47 Withdrawal of consent. A push notification is addressed to a device token, not to a telephone number — but if your campaign also sends SMS, that leg is a different regime with its own duties, and you should take advice on it rather than assume the app covers you.
Measuring whether any of it worked
You cannot manage notification frequency without a delivery number, and the honest position is that the platforms do not give you a single clean one. Firebase Cloud Messaging's delivery reporting defines four distinct metrics, and knowing which is which stops a lot of arguments.
| Metric | What it means | Availability |
|---|---|---|
| Sends | The message "has been enqueued for delivery or has been successfully passed to a third-party service like APNs for delivery" | Android and Apple platforms. "Sends statistics might lag for a couple of hours." |
| Received | The message "has been received by the app" | "available only on Android devices", and only where the device has "FCM SDK 18.0.1 or higher installed" |
| Impressions | "The display notification has been displayed on the device while the app is in the background" | "available only for notification messages on Android devices" |
| Opens | "The user opened the notification message" | "Reported only for notifications received when the app is in the background" |
Firebase also notes that "the reporting of many of the statistics on this page, are subject to delays up to 24 hours", and that custom analytics labels have a max length of 50 characters with "up to 100 unique labels per day".
The asymmetry is the thing to take away: Sends means you handed the message to Apple, not that anybody saw it, and Received and Impressions are Android-only. Anyone presenting you a single blended "delivery rate" across both platforms is presenting an estimate. Treat notification numbers the way you treat the rest of your post-launch instrumentation — as one input among several, which is the argument we make in measuring app success after launch.
What this costs to build properly
Done at design time, notifications are a modest slice of a build: a permission-request moment placed in a real context, a preferences screen, a channel structure on Android, a server-side send path with retry and expiry handling, and the deep links that make each notification land somewhere useful. Done afterwards, the expensive parts are the ones you cannot undo — an Android channel structure that is already fixed on installed devices, and an iOS install base that has already seen and dismissed your one prompt.
At Namtech this sits inside the normal build rather than as a separate invoice line. Our published tiers start at SGD 20,000 for a Starter / MVP, SGD 38,000 for a Business App and SGD 90,000 for an Enterprise / Platform build, with every project scoped individually — those are honest starting points, not teaser rates. Where a project needs a full marketing-automation platform behind its notifications rather than transactional sends, we scope and quote that separately rather than burying it. After go-live, Maintenance & Support from 15% of build cost per year is where notification behaviour keeps getting checked as the operating systems change — and they have changed a great deal in this specific area over the last few releases.
One caveat we will not dress up: nobody can promise you an opt-in rate. It depends on your category, your timing, and whether the first notification a person receives was worth the interruption. We would rather scope the mechanism well and let you judge the outcome on your own numbers.
Questions to ask your vendor
- "What target SDK are we shipping on Android?" If the answer is below Android 13 (API 33), you have handed the timing of your one permission prompt to the operating system, and a single Don't allow sticks until reinstall.
- "Where in the journey does the permission prompt appear, and what do we show before it?" Both Apple and Google advise asking in context and explaining why. "On first launch" is the answer that wastes the prompt.
- "What are our notification channels, and who signed off on the list?" Channel behaviours cannot be changed after creation, so this list is close to permanent. Transactional, account and security, and marketing should be separate.
- "Are we using provisional authorization on iOS?" There is a real trade-off either way, but the vendor should know the option exists and be able to say why they chose as they did.
- "Show me the notification preferences screen." Guideline 4.5.4 requires an in-app opt-out for marketing messages, and withdrawal of consent is a named section of the PDPA. If the screen does not exist in the designs, it does not exist.
- "What happens if a push does not arrive?" APNs stores one notification per bundle ID for 30 days or less and may reorder or throttle. Anything that must be seen needs a fallback path inside the app.
The operating system decides whether your notification can arrive; your consent screen decides whether it should — and the platforms have made it clear that getting the first without the second is a review problem, not a growth strategy.
Sources
- Apple — Asking permission to use notifications (single prompt, asking in context, provisional authorization, checking authorisation status before scheduling).
- Apple — Generating a remote notification (4 KB / 4096-byte payload limit; 5 KB / 5120 bytes for VoIP).
- Apple — Sending notification requests to APNs (30-day storage ceiling, one stored notification per bundle ID, reordering, priority 5/1 bursts and throttling, HTTP/2 with TLS 1.2 or later, ports 443 and 2197).
- Apple — App Store Review Guidelines, guideline 4.5.4 (push must not be required for the app to function, must not carry sensitive personal or confidential information, explicit in-app opt-in and opt-out for promotions or direct marketing).
- Google — Notification runtime permission (POST_NOTIFICATIONS on Android 13 / API 33+, off by default for new installs, prompt timing by target SDK, pre-grant on upgrade and its eligibility conditions, exemptions).
- Google — Create and manage notification channels (mandatory since Android 8.0 / API 26, silent failure without a channel, behaviours immutable after creation, "categories" in the UI).
- Firebase — Understanding message delivery (definitions of Sends, Received, Impressions and Opens; Android-only availability; up-to-24-hour reporting delay; analytics label limits).
- Google Play — Ads policy (ads must not simulate or impersonate app or OS notification interfaces).
- Google Play — Deceptive Behavior policy (no ads mimicking system notifications or warnings; clear in-app disclosures and explicit consent before changing device settings).
- Singapore Statutes Online — Personal Data Protection Act 2012 (long title; Part 4 Consent, ss 13–17; Division 2 Purpose, ss 18 and 20; Part 6A Notification of Data Breaches; Part 9 Do Not Call Registry, Division 3 "Specified message to Singapore telephone number", ss 43, 46 and 47).
- Namtech — Pricing (SGD 20,000 / 38,000 / 90,000; Maintenance & Support from 15% of build cost per year).

