Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Push Notifications for Mobile Apps

By Kokil Thapa | Last reviewed: September 2026

Users ignore email. They still tap push notifications for mobile apps when the message is timely and relevant. That makes push one of the highest-leverage retention channels for booking apps, eCommerce carts, and client portals. The hard part is not the banner itself. It is token lifecycle, platform differences, and a backend that can send millions of messages without duplicating orders or leaking PII. If you already ship REST APIs for mobile clients, push belongs in the same architecture conversation as auth, webhooks, and queue workers.

How do push notifications for mobile apps work?

Push is an indirect delivery path. Your server never opens a socket to the phone. It talks to Apple or Google. Those platforms maintain persistent connections to devices and wake the app when a payload arrives.

The flow has four actors: your app, your API, the push gateway, and the device OS. Each step has a contract you must honour in production.

Push Notification Delivery PathMobile AppRequests tokenYour APIStores tokenQueue WorkerBuilds payloadFCM / APNsPlatform GWEvent Triggers (order shipped, booking reminder, document ready)Domain event fires job, not inline HTTP from controllerDevice OS displays alertUser taps deep link into app screen
End-to-end push notifications for mobile apps: token registration, queued delivery, and platform gateway handoff

Registration and permission

On first launch, the app asks the OS for notification permission. iOS requires an explicit opt-in. Android 13+ also prompts at runtime. If the user declines, you cannot recover silently. You need an in-app fallback such as email or SMS.

After permission, the SDK returns a device token (FCM registration token or APNs device token). The app POSTs that token to your backend alongside user ID, platform, app version, and locale.

Delivery and display

When a business event occurs—payment confirmed, trek departure reminder, legal document uploaded—your backend enqueues a job. The worker builds a JSON payload and calls the gateway API. The OS renders the notification even when the app is killed.

Payloads split into notification fields (title, body, sound) and data fields (order ID, deep link route). Keep data minimal. Large payloads fail on some networks in Nepal where mobile data is still metered.

What is the difference between FCM, APNs, and web push?

Android and iOS use different gateways. You cannot send one HTTP request and reach both platforms unless you use a cross-platform provider or abstract the difference in your own service layer.

Firebase Cloud Messaging (FCM) handles Android and can also relay to APNs when configured. Apple Push Notification service (APNs) is mandatory for native iOS. Web push uses the W3C Push API with a service worker—useful when you are not ready for native apps. See the progressive web apps guide for that path.

ChannelGatewayToken typeBest forGotcha
Android nativeFCMRegistration tokenPlay Store appsTokens rotate; stale tokens return 404
iOS nativeAPNsDevice tokenApp Store appsRequires .p8 key or cert; sandbox vs production
Cross-platformFCM + APNs configPlatform-specificReact Native, Flutter teamsStill two credential sets behind one SDK
Web / PWABrowser push servicePush subscription JSONBudget-first rolloutiOS Safari limits until installed to home screen
Backend-onlyOneSignal, Pusher BeamsVendor tokenSmall teams without DevOpsVendor lock-in and per-MAU pricing
Platform Push Channels ComparedFCMAndroid primaryHTTP v1 APIOAuth2 service accountAPNsiOS mandatoryJWT or certificateSandbox vs prodWeb PushService workerVAPID keysNo app storeUnified Backend Abstraction Layerdevice_tokens table, platform enum, queue jobsInvalidate on 410 / Unregistered responsesLog delivery status for support debugging
FCM, APNs, and web push feed a single backend abstraction for push notifications for mobile apps

For most client projects I work on, the mobile team owns SDK integration. I own the API contract, token storage, and queued delivery. That split keeps responsibilities clear and avoids controllers calling FCM synchronously during checkout.

How should you store and manage device tokens on the backend?

Token management is where push systems quietly fail. Users reinstall apps. OS updates rotate tokens. People log in on two phones. Treat tokens as ephemeral credentials, not permanent user attributes.

Store one row per token, not one token column on the users table. A typical Laravel migration looks like this:

Schema::create('device_tokens', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('token', 512)->unique();
    $table->enum('platform', ['ios', 'android', 'web']);
    $table->string('app_version', 20)->nullable();
    $table->string('locale', 10)->default('en');
    $table->timestamp('last_used_at')->nullable();
    $table->timestamps();
    $table->index(['user_id', 'platform']);
});

Upsert on registration: same token updates last_used_at. Logout deletes the row for that device. Never broadcast to every token without checking user notification preferences.

Invalidation rules

When FCM returns UNREGISTERED or APNs returns status 410, delete the token immediately. Retry logic should not hammer dead endpoints. I batch invalidations in the same job that sent the push.

For high-volume apps, cache active token counts in Redis only if you have measured a read bottleneck. Most booking and eCommerce apps are fine with indexed MySQL queries on user_id.

  1. App opens → POST /api/v1/device-tokens with bearer token.
  2. Backend upserts row and returns 204.
  3. Business event fires → job loads tokens for affected users.
  4. Worker sends per platform, logs success/failure.
  5. Dead tokens are deleted; transient errors retry with backoff.

Validate payloads with a JSON formatter during development. Production logs should never print full tokens—they are bearer-like secrets.

How do you implement push notifications in Laravel?

Laravel ships a notification system that supports multiple channels. Email and database notifications are common. Push fits the same pattern if you add a custom channel or use a community driver. The related Laravel notifications beyond email article covers channel architecture in depth.

On PHP 8.3+ with Laravel 12 or 13, this is the pattern I use on production apps:

Install a push driver

For FCM HTTP v1, packages such as kreait/laravel-firebase wrap authentication and message building. Configure the service account JSON in .env, never in git.

FIREBASE_CREDENTIALS=/var/www/shared/firebase-service-account.json
FCM_PROJECT_ID=your-project-id

Create a notification class

<?php

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use NotificationChannels\Fcm\FcmChannel;
use NotificationChannels\Fcm\FcmMessage;

class OrderShipped extends Notification
{
    public function __construct(private int $orderId) {}

    public function via(object $notifiable): array
    {
        return [FcmChannel::class, 'database'];
    }

    public function toFcm(object $notifiable): FcmMessage
    {
        return FcmMessage::create()
            ->title('Your order is on the way')
            ->body('Track delivery in the app.')
            ->data(['order_id' => (string) $this->orderId]);
    }
}

Dispatch through a queue

Always queue notification sending. A payment webhook should not wait on Google’s API latency.

$user->notify(new OrderShipped($order->id));

Ensure ShouldQueue is implemented on the notification or run the notifiable through a queued listener. Pair this with Horizon or database queue workers on Ubuntu 22/24—the same stack I use for Linux production hosting.

Laravel Push Job PipelineOrderShippedEvent ListenerQueue JobFCM APIFailed job → retry 3x → log → alert if still failingNever lose order state because push failedIdempotency key on payment webhooksPrevents duplicate push on gateway retryStore processed webhook IDs in Redis or DB
Queued Laravel jobs with idempotent webhooks prevent duplicate push notifications for mobile apps

For WooCommerce-backed mobile storefronts, order events often originate in WordPress. A webhook into Laravel—or direct integration via the WooCommerce REST API—should trigger the same notification classes. One source of truth for message copy avoids the app saying "shipped" while email says "processing".

What security and privacy rules apply to push payloads?

Push travels through third-party infrastructure. Assume Google and Apple can read notification title and body fields. Never put passwords, full card numbers, or unredacted legal documents in the alert text.

Put sensitive detail behind an authenticated in-app fetch. The notification says "New message" and the app loads content after login. This aligns with mobile app security basics and Nepal’s data-handling expectations for client portals.

  • Sign APNs requests with a rotated .p8 key stored outside the web root.
  • Restrict Firebase service accounts to Cloud Messaging only.
  • Rate-limit the token registration endpoint to prevent token flooding attacks.
  • Respect user opt-out flags before every send—not only at registration.
  • Log delivery metadata, not message body content, in production.

Deep links must validate the target resource belongs to the logged-in user. A guessable order ID in a data payload is an IDOR waiting to happen.

What are common push notification mistakes in production?

Most failures I debug are operational, not SDK bugs. Teams treat push as a frontend feature and skip backend discipline.

Sending from the request cycle

A controller that calls FCM inline during checkout adds 200–800 ms latency. Worse, a timeout can mark payment ambiguous while the user already received a push. Queue everything.

Ignoring timezone and locale

A booking reminder at 02:00 local time gets notifications disabled. Store user timezone on the profile. Schedule reminders with Laravel’s task scheduler and respect quiet hours. For Nepali apps, BS date display belongs in the app UI—not in the push channel logic.

Over-notification

Marketing teams want daily blasts. Product teams want retention. Users uninstall. Cap promotional pushes per week. Transactional messages—OTP, receipt, booking change—get priority.

Should You Send This Push?New event?TransactionalSend immediatelyPromotionalCheck opt-inUser opted in?Yes → queue jobQuiet hours?Delay until morningLog send + respect uninstall
Decision flow for transactional vs promotional push notifications for mobile apps

Skipping staging credentials

APNs sandbox tokens fail against production endpoints. I have seen week-long debug sessions caused by one wrong boolean. Document which build flavour maps to which APNs environment. Automate checks in mobile CI/CD with Fastlane if your team uses it.

No fallback channel

Push is best-effort. SMS or email should confirm critical actions—payment received, court appointment booked, trek permit issued. On a trekking booking platform like Adventure Third Pole Trek, departure changes need guaranteed delivery through at least two channels.

How do web push and native push fit together?

Not every business needs an App Store release on day one. Web push via a service worker covers Android desktop and many Android phones. iOS web push improved but still expects a installed PWA for reliable delivery.

A sensible 2026 rollout for a Nepal SMB:

  1. Launch responsive web app with optional web push.
  2. Measure repeat usage and notification opt-in rate.
  3. Ship native app when offline features or store presence justify the cost—often Rs 800,000–2,000,000 (~USD 6,000–15,000) for a focused v1.
  4. Reuse the same Laravel notification classes; swap the channel driver per platform.

MDN’s Push API documentation is the authoritative reference for VAPID keys and subscription objects. Keep web and native tokens in the same table with a platform discriminator.

For eCommerce, tie push to cart and order events the same way you would wire Khalti or eSewa callbacks—idempotent, logged, and testable. See eCommerce development for full checkout architecture.

How do you test and monitor push delivery?

Testing starts in sandbox. Use Firebase console for manual Android sends. Use APNs sandbox with development provisioning profiles on real devices—simulators do not fully replace device behaviour for remote notifications.

Automated tests should mock the HTTP client. Assert the notification class builds the correct payload. One integration test against sandbox per deploy is enough for most teams.

Monitor these metrics:

  • Send success rate by platform
  • Token invalidation rate (spike means app bug or cert rotation)
  • Queue latency for notification jobs
  • Tap-through rate per notification type
  • Opt-out rate after promotional campaigns

Pair push monitoring with broader testing and optimization practices. OpenTelemetry traces from the related instrumentation guide help correlate slow checkout with failed notification jobs.

On the marketing side, poor mobile engagement hurts mobile-first indexing signals indirectly when users bounce back to search. Push is retention, not SEO—but retained users generate the behavioural data that supports organic growth.

Key Takeaways

  • Push notifications for mobile apps flow through FCM and APNs—your backend stores tokens and queues delivery, never calling gateways inline from controllers.
  • Use a dedicated device_tokens table, delete stale tokens on 404/410 responses, and never store tokens in JWTs or session cookies.
  • Keep notification title/body free of PII; load sensitive content after the user opens the app and authenticates.
  • Separate transactional and promotional sends with opt-in checks, quiet hours, and weekly caps.
  • Laravel notification channels plus queue workers give you the same architecture for native push, web push, email, and SMS.
  • Always maintain a fallback channel for critical business events—push alone is not guaranteed delivery.

People Also Ask

Do push notifications work when the app is closed?

Yes. That is the primary value of push notifications for mobile apps. The OS receives the payload from FCM or APNs and renders the alert independently of app process state. Data-only messages may require background handler support on Android.

How much do push notifications cost?

FCM and APNs delivery is free at platform level. Costs come from backend compute, queue infrastructure, and optional third-party providers. Expect Rs 0 direct per message unless you use a paid aggregator with per-MAU pricing above free tiers.

Can Laravel send push notifications without a mobile app?

Yes. Laravel can send web push through service worker subscriptions using the same notification system. Native Android and iOS require respective SDKs in those apps, but the server-side pattern stays identical.

Why do push notifications stop working after an app update?

Common causes include expired APNs certificates, wrong sandbox/production endpoint, changed Firebase google-services.json, or tokens not re-registered on first launch after update. Check gateway error responses before blaming the mobile codebase.

Ship push the right way from your backend

Push notifications for mobile apps succeed when backend engineers treat them like payments: idempotent jobs, clear contracts, token hygiene, and fallbacks when delivery fails. Native SDK work belongs to your mobile team or agency partner. The API, queue layer, and notification rules belong in the same Laravel or Symfony codebase that already powers your custom software and enterprise workflows.

If you are planning a booking app, eCommerce companion, or client portal with real-time alerts, map your event list before you write SDK code. I help teams design that layer—token APIs, queued delivery, and integration with existing mobile architecture—so notifications ship reliably in production. Contact us to discuss your project, or browse the portfolio for apps that already depend on timely user alerts.

Frequently Asked Questions

Push notifications for mobile apps are alerts delivered by platform gateways—Firebase Cloud Messaging on Android and Apple Push Notification service on iOS—after your backend stores device tokens and sends signed payloads when business events occur.

Push is an indirect path: your server never opens a socket to the phone. The app requests OS permission, receives a device token, and POSTs it to your API with user ID, platform, app version, and locale. When an event fires—payment confirmed, booking reminder, document uploaded—your backend enqueues a job. A worker builds a JSON payload and calls FCM or APNs. The OS renders the alert even when the app is killed. Payloads split into notification fields (title, body, sound) and data fields (order ID, deep link route).

Android native apps use FCM registration tokens; iOS requires APNs device tokens with a .p8 key or certificate and separate sandbox versus production environments. FCM can relay to APNs when configured, but you still maintain two credential sets for cross-platform apps. Web push uses the W3C Push API with a service worker and VAPID keys—good for budget-first rollout, though iOS Safari limits apply until the PWA is installed to the home screen. Backend-only vendors like OneSignal or Pusher Beams abstract this but add per-MAU pricing and vendor lock-in.

FCM and APNs delivery is free at the platform level. Direct per-message cost is Rs 0 unless you use a paid aggregator with per-MAU pricing above free tiers. Real costs come from backend compute, queue workers, and optional third-party providers.

Treat tokens as ephemeral credentials, not permanent user attributes. Store one row per token in a dedicated device_tokens table—not a single token column on users—with platform, app_version, locale, and last_used_at. Upsert on registration; delete the row on logout. When FCM returns UNREGISTERED or APNs returns status 410, delete immediately and do not retry dead endpoints. Batch invalidations in the same job that sent the push. Most booking and eCommerce apps handle token lookups with indexed MySQL queries on user_id without needing Redis unless you have measured a read bottleneck.

On PHP 8.3+ with Laravel 12 or 13, use Laravel's notification system with a custom FCM channel or a community driver such as kreait/laravel-firebase for FCM HTTP v1. Configure the Firebase service account JSON outside git via .env. Create a notification class returning FcmChannel alongside database or email channels, build title, body, and minimal data fields in toFcm(), and always dispatch through a queue—never call FCM synchronously from a controller during checkout. Pair with Horizon or database queue workers on Ubuntu 22/24. For WooCommerce-backed storefronts, wire order webhooks into the same notification classes so message copy stays consistent across channels.

Yes. The OS receives the payload from FCM or APNs and renders the alert independently of app process state. Data-only messages may require background handler support on Android.

Assume Google and Apple can read notification title and body fields. Never put passwords, full card numbers, or unredacted legal documents in alert text—say "New message" and load sensitive content after authenticated in-app fetch. Sign APNs requests with a rotated .p8 key stored outside the web root. Restrict Firebase service accounts to Cloud Messaging only. Rate-limit the token registration endpoint against token flooding. Respect user opt-out flags before every send. Log delivery metadata, not message body content. Deep links must validate the target resource belongs to the logged-in user—a guessable order ID in a data payload is an IDOR risk.

Sending from the request cycle adds 200–800 ms latency and can mark payments ambiguous while the user already received a push—queue everything. Ignoring timezone causes booking reminders at 02:00 local time and drives opt-outs; store user timezone and respect quiet hours. Over-notification from marketing blasts leads to uninstalls—cap promotional pushes weekly and prioritise transactional messages. Using APNs sandbox tokens against production endpoints causes week-long debug sessions—document build flavour to environment mapping. Skipping fallback channels leaves critical events like payment confirmation or trek departure changes on best-effort delivery alone.

Yes. Laravel can deliver web push through service worker subscriptions using the same notification system and channel architecture. Native Android and iOS still require respective SDKs in those apps, but the server-side pattern—token storage, queued jobs, notification classes—stays identical. Keep web and native tokens in the same table with a platform discriminator and swap the channel driver per platform.

A sensible 2026 rollout for a Nepal SMB: launch a responsive web app with optional web push, measure repeat usage and opt-in rate, then ship a native app when offline features or store presence justify the cost—often Rs 800,000–2,000,000 (~USD 6,000–15,000) for a focused v1. Reuse the same Laravel notification classes across both. For eCommerce, tie push to cart and order events the same way you wire Khalti or eSewa callbacks—idempotent, logged, and testable.

Start in sandbox: Firebase console for manual Android sends, APNs sandbox with development provisioning on real devices—simulators do not fully replace remote notification behaviour. Automated tests should mock the HTTP client and assert the notification class builds the correct payload; one integration test against sandbox per deploy suffices for most teams. Monitor send success rate by platform, token invalidation rate spikes, queue latency for notification jobs, tap-through rate per notification type, and opt-out rate after promotional campaigns. OpenTelemetry traces help correlate slow checkout with failed notification jobs.

Common causes include expired APNs credentials, token rotation after reinstall or OS update, and sandbox versus production environment mismatch. FCM and APNs tokens are not permanent—users reinstall apps, log in on multiple devices, and stale tokens return 404 or 410 from the gateway. If your mobile build switched from development to production provisioning without updating backend APNs endpoint configuration, every send silently fails. Fix by re-registering tokens on app launch, deleting invalidated tokens immediately on gateway errors, and documenting which build flavour maps to which APNs environment.

For most client projects, the mobile team owns SDK integration while the backend developer owns the API contract, token storage, and queued delivery—that split avoids controllers calling FCM synchronously during checkout. Third-party providers like OneSignal or Pusher Beams suit small teams without DevOps but introduce vendor lock-in and per-MAU pricing. Building on FCM HTTP v1 and APNs directly with Laravel notification channels gives full control, keeps credentials in your infrastructure, and aligns push with the same queue-and-webhook architecture you already use for auth and payment callbacks.

Transactional messages—OTP, receipt, booking change, payment confirmed—get priority and should send regardless of marketing opt-in, though users can still disable OS-level notifications entirely. Promotional pushes need explicit consent, weekly caps, and quiet-hour scheduling via Laravel's task scheduler respecting stored user timezone. A booking reminder at the wrong local hour gets notifications disabled permanently. On a trekking booking platform, departure changes need guaranteed delivery through at least two channels—push plus SMS or email—because push alone is best-effort and not guaranteed delivery.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: