Push is one of the most powerful tools in the mobile arsenal. It is also the fastest way to lose a user.
The fastest way to drive a user to disable notifications is to send them one too many. The fastest way to drive them to delete the app is to do it twice. Push notifications are a privilege, and the backend that decides what to send is more important than the SDK that delivers it.
The decision pipeline
Every notification flows through four checks before APNs / FCM:
- Eligibility: is the user opted in for this notification type?
- Frequency cap: have they received too many in this window?
- Quiet hours: is it the right time of day in their timezone?
- Personalization: do we have the data to make this relevant?
Skipping any of these is how you end up sending "Don't forget to log in!" at 3 AM to a user who has been active for an hour.
Quiet hours are not optional
Default to the user's local timezone. Default quiet hours: 10 PM to 8 AM. Make them configurable. Apple and Google both reward apps that respect these — and punish apps that do not, via Focus modes and Notification Channels.
Per-channel preferences
Android forces this with Notification Channels. iOS does not, but well-behaved apps offer it anyway. Transactional, marketing, social, and product updates are different channels with different defaults. Let the user mute marketing without muting password resets.
Measure delivered, not just sent
The push payload was sent. APNs accepted it. The device may have been off. The user may have notifications disabled. The OS may have suppressed it. Track delivered, opened, and converted — not just sent. Mature notification systems measure end-to-end.
The escape hatches
Always include a deep link. Always include an unsubscribe path. Always make the notification self-explanatory — "Acme: your order shipped" not "Update from Acme." Users who open and act represent your future retention.