NewHuxly MCP — Connect Claude, Cursor & Codex.Learn more
How to Add Push Notifications to a Mobile App
Back to Blog
GuideSep 9, 202612 min read

How to Add Push Notifications to a Mobile App

Contents

Push notifications are useful when they bring someone back to a task they already care about: a reply needs attention, an order changed, a booking was confirmed, or a time-sensitive reminder is due. They become noise when they exist only to create another open.

A reliable implementation is not just a device token and a “Send” button. It needs a clear event, permission at the right moment, a trusted backend, a safe destination after the tap, user controls, and a way to learn whether the notification helped.

Key takeaways:

Ask for notification permission after the user sees its value, store tokens as revocable device records, send from a trusted backend rather than the app, deep-link to an authorized destination, separate required service updates from optional engagement, and test permission, token, and tap flows on real release builds.

Start with one user event

Write the notification as a product rule before choosing a provider.

Product eventUseful notificationDestination after tapCan the user turn it off?
A customer’s order changes status“Your order is out for delivery”That order’s tracking screenUsually no for essential status updates
A marketplace seller receives an offer“You received an offer on your bike”The offer threadYes
A user’s coach replies“Maya replied to your plan”The specific conversationYes
A medication reminder is due“Time for your 8:00 PM reminder”Today’s reminderYes, with schedule controls
A new comment arrives“3 new comments on your post”The post or activity feedYes

Avoid starting with “send a notification when someone has been inactive for three days.” First identify the missed value: an unfinished plan, a saved item that changed, or a collaboration task that needs a response. If the action after the tap is unclear, the notification is probably not ready.

Keep transactional and engagement notifications separate. A booking cancellation, security alert, or completed payment is part of the service. A weekly prompt to return is optional marketing. They need different preferences, copy, frequency limits, and reporting.

Understand the delivery path

A remote push crosses several systems. The mobile app registers a device token. Your backend decides whether an event deserves a notification. A provider then delivers it through Apple Push Notification service (APNs) or Firebase Cloud Messaging (FCM).

text
User action or scheduled event
  -> backend verifies the event and recipient
  -> backend checks notification preferences and token status
  -> push provider sends to APNs or FCM
  -> operating system presents, delays, groups, or suppresses it
  -> user taps
  -> app opens a safe deep link and fetches fresh data

The operating system, not your app, controls final presentation. A valid send does not guarantee that a banner appears immediately: the user may have denied permission, enabled Focus mode, muted a channel, or lost connectivity.

For Expo projects, Expo Notifications can obtain device or Expo push tokens, handle incoming notifications, and react to notification taps. Expo’s push service simplifies the APNs/FCM handoff, while a direct provider setup gives your backend more control. Either way, the send credentials belong in a trusted server environment, not in the mobile client.

Ask for permission after value is visible

Do not show the operating-system prompt on the first launch before the user understands the app. Let the person complete an action that makes notifications useful, then show a short pre-permission explanation.

For example:

  1. A buyer enables order tracking.
  2. The app explains: “Get delivery updates for this order. You can change this anytime.”
  3. The user taps Turn on updates.
  4. The app requests the system permission.
  5. If declined, the order screen still works and offers email or in-app status checks.

On Android 13 and later, notification permission is opt-in. With Expo, create an Android notification channel before requesting an Expo or device push token; its documentation explains the required order. On iOS, distinguish between a user who has not decided, denied access, granted access, or has provisional authorization. Do not repeatedly trigger the system prompt after a denial—show a respectful Settings path only when the user asks to enable a feature.

A good permission screen answers three questions:

  • What specific updates will arrive?
  • How often will they arrive?
  • What can the user control later?

“Enable notifications” is not an explanation.

Treat each token as a device record

A token identifies an app installation, not a permanent user identity. A person may use multiple phones, reinstall the app, sign out, or disable permission. Model it accordingly.

FieldWhy it matters
idStable database record
user_idAuthenticated owner, if signed in
tokenProvider token; protect it like account data
providerExpo, APNs, or FCM
platformiOS or Android
installation_idDistinguishes multiple devices
permission_statusPrevents pointless sends
last_seen_atHelps retire stale records
disabled_atKeeps an audit trail after a failure or sign-out

Register or refresh the token after permission is granted and whenever the app starts from an authenticated session. Tie the record to the verified user on the server; never let the client claim another user’s ID.

When the user signs out, revoke or disassociate the device record. When a provider reports an invalid or unregistered token, mark it inactive. Do not keep attempting the same failed send forever.

Send only from the backend

The app may request an action, but it should not decide and send the final notification. Your backend has the event data, recipient authorization, preference state, rate limits, and provider credentials.

A safe send flow looks like this:

text
Order status changes to "out_for_delivery"
  -> backend confirms the change is real
  -> find the order's authorized customer
  -> read the customer's delivery-update preference
  -> find active device records
  -> create one notification log entry
  -> send provider payloads
  -> store provider receipts and retire invalid tokens

Firebase Cloud Messaging likewise separates the client app from a trusted environment that builds and sends messages. Never ship an FCM server credential, APNs private key, or provider secret inside an Expo, React Native, Flutter, or Swift app.

Create a notification log with the event type, recipient, destination, sent time, provider response, and whether the user opened it. This makes duplicate sends and support investigations much easier to diagnose.

Make every notification open a safe screen

A notification payload should contain only the information needed to route the user, such as:

json
{
  "type": "order_status_changed",
  "orderId": "ord_123",
  "url": "/orders/ord_123"
}

When the app opens:

  1. Read the route data.
  2. Restore the user session if necessary.
  3. Fetch the current record from the backend.
  4. Verify the signed-in user may access it.
  5. Show an unavailable state if the record was deleted, cancelled, or no longer belongs to them.

Do not put sensitive data in a payload just because the app can display it. Notification previews can appear on a locked screen, and a stale payload is not a source of truth. Expo documents how to respond to taps and route with deep links in its notification handling guide.

Design notification categories and controls

A single master toggle is rarely enough. Create understandable categories that map to real user choices.

CategoryExamplesDefault
Account and securityNew login, password resetOn
Transactional updatesDelivery, appointment, payment statusOn when relevant
Direct activityReplies, messages, assigned tasksOn
RemindersHabits, due dates, saved plansUser-controlled
Product updatesTips, new features, promotionsOff or opt-in

Keep the controls in the app even though iOS and Android also offer operating-system controls. Your backend must respect the app-level preferences before it calls a provider.

On Android, notification channels also let users control categories at the operating-system level. Do not create a channel for every individual message; use a small, stable set such as messages, orders, and reminders. Once users lower a channel’s importance, your app should still work without banners or sound.

Protect attention with frequency and timing rules

A notification system needs limits before it needs clever copy.

Set rules for:

  • Maximum promotional notifications per week.
  • Quiet hours in the user’s selected timezone.
  • A cooldown after a user ignores a similar prompt.
  • Deduplication when the same event is processed twice.
  • Grouping for multiple events, such as “3 new comments.”
  • A clear priority order when several events compete.

Use local time only when you know the user’s timezone and have a meaningful reason to send at that time. “8:00 AM everywhere” is not the same as “8:00 AM for this user.”

For reminders that must occur on the device even without a network connection, local scheduling can be appropriate. For server-side events such as a new order or message, use remote notifications. Keep these two cases separate in your product model.

Handle foreground, background, and failure states

The experience differs depending on app state.

StateExpected behavior
App open in the relevant screenUpdate the screen; do not interrupt with a redundant banner
App open elsewhereShow an in-app message only when it helps
App backgroundedLet the system present the configured notification
App closed, then opened from a tapRestore session, route safely, fetch fresh data
Permission deniedKeep the feature usable and offer in-app/email alternatives where sensible
Token invalidStop sending and register a new token on a future app session

Remote push testing should use a development or production build, not just a preview. In particular, Expo notes that remote push support is unavailable in Expo Go on Android from SDK 53; use a development build or release build for the real flow.

Measure whether notifications help

Open rate is not enough. A dramatic notification may earn taps and still damage trust.

Track the full path:

MetricWhat it tells you
Eligible usersWhether the audience is defined correctly
Send and provider errorsToken or provider health
Delivered/opened where availableBasic reach and interest
Destination completedWhether the notification led to useful action
Preference changes and opt-outsWhether it felt excessive
7- and 30-day retention by cohortWhether the system creates lasting value

Compare a notification against a clear product outcome, such as completed check-ins, attended appointments, resolved support tasks, or repeat purchases. Do not optimize for notifications sent.

Test the whole system before launch

Test on physical iOS and Android devices with release-like credentials.

  • Permission granted, denied, and later changed in Settings.
  • A user with two devices and a user who signs out.
  • Foreground, background, and closed-app taps.
  • A destination the user can no longer access.
  • Expired or invalid tokens.
  • Duplicate event delivery and retry behavior.
  • Android channel changes and iOS notification settings.
  • Quiet hours, timezone changes, and grouped events.
  • A slow or unavailable backend after the user taps.
  • Sensitive content with lock-screen previews disabled.

Use the broader mobile app testing guide before store submission.

Build a useful notification system with Huxly

Huxly can help you build the notification settings screens, authenticated device records, backend event logic, deep-link destinations, and real-device testing flow in one mobile app project. The important part is defining the user event and safety rules first; then the app and backend can be built around a system people will choose to keep enabled.

FAQ

Do I need a backend to send push notifications?

For notifications triggered by orders, messages, subscriptions, or other shared data, yes. A trusted backend should decide the recipient, enforce preferences, and keep provider credentials private. Local notifications can run on-device for simple reminders.

Should I ask for notification permission on the first screen?

Usually no. Ask after the user understands the benefit, such as enabling delivery tracking or message alerts. An early unexplained prompt is easy to deny.

Can I send the full private message in the notification body?

You can, but consider lock-screen privacy first. A safer default is a generic preview such as “You have a new message,” then fetch the content after authorization in the app.

Why does a push work in development but not after release?

Credentials, bundle identifiers, Android channels, provider configuration, and build type can all differ. Test the same release-like build and environment you plan to submit.

How do I stop duplicate notifications?

Give each product event an idempotency key, log the planned notification before sending, and prevent a second worker or retry from creating another notification for the same recipient and event.

Are push notifications required for App Store approval?

No. They are optional. If you use them, make their purpose clear, respect permissions, and ensure the app still handles the related feature when notifications are unavailable.

Conclusion

A good push notification is a continuation of a useful product moment, not a shortcut to more opens. Define the event first, request permission in context, keep provider credentials on the backend, and route every tap to fresh authorized data.

When the system also respects preferences, quiet time, token changes, and real-device failure cases, notifications become a dependable part of the app instead of a source of churn.