Skip to content
Advanced iOS push notifications: scaling APNs in production

18 Minutes

Advanced iOS push notifications: scaling APNs in production

Fix Bugs Faster! Log Collection Made Easy

Get started

The Apple Push Notification Service (APNs) allows developers to send real-time alerts and data to Apple devices. But it can create a number of problems as your app scales including silent throttling, deep link errors and push payload incompatibility. This post will help you proactively avoid these issues.

You’ll learn about:

  • The most common push notification issues that appear in large iOS deployments.
  • Why some issues appear only at large scale.
  • Technical challenges across APNs, devices and backend systems.
  • The practical approaches teams use to diagnose and fix them.

This guide is intended for developers already using push notifications or planning to operate notification systems at scale. If you’re just starting out with push notifications, we’d suggest you begin with our foundational guide.

Table of Contents

10 common iOS push notification problems in production

Many developers will know that APNs may reject push notifications if the token is old or invalid. However this is only one issue to be aware of.

Even when notifications are accepted by APNs, they may still fail somewhere in the delivery or handling pipeline.

Here are 10 of the most important issues to be mindful of:

  1. Those aforementioned device token lifecycle problems.
  2. Silent push throttling by iOS.
  3. Limited delivery observability after APNs acceptance.
  4. Deep link routing failures after a push tap.
  5. APNs throughput issues or queue bottlenecks.
  6. Push payload incompatibility across app versions.
  7. Notification service extension failures.
  8. Incorrect collapse identifiers replacing messages.
  9. Notification ordering issues during retries.
  10. Long-term notification permission decay.

Now let’s examine each of these in turn.

1. Device token lifecycle problems

Push notifications rely on a device token generated by APNs. This token identifies the specific device that should receive notifications.

Many implementations treat this token as stable. In reality, device tokens can change during the lifecycle of the app and device. When outdated tokens remain stored in the backend, push requests may succeed while the notifications never reach the intended device.

Typical production symptom

Push requests appear successful, but a large portion of notifications never reach users’ devices.

Backend logs may show APNs accepting the request, yet delivery rates gradually decline. Over time this can affect 30–40% of push notifications if stale tokens accumulate.

APNs may also return errors such as:

410 Unregistered
400 BadDeviceToken

These responses indicate that the token stored by the backend is no longer valid.

Common causes

Device token issues usually occur when:

  • The app is reinstalled or installed on a new device.
  • The device is restored from backup.
  • The operating system updates and refreshes the token.
  • The same user logs in from multiple devices.
  • The backend never removes outdated or invalid tokens.

Recommended implementation

Device tokens should be treated as temporary infrastructure identifiers, not permanent user IDs.

GuidelinePractical implementation
Register tokens regularlySend the latest token to the backend whenever the app launches
Store tokens per deviceMaintain a list of device tokens per user instead of overwriting them
Remove invalid tokens immediatelyDelete tokens when APNs returns 410 Unregistered or 400 BadDeviceToken
Track token freshnessStore metadata such as last_updated, app_version, and device model
Run cleanup jobsPeriodically remove tokens from devices inactive for long periods

In mature push systems, token management becomes an automated maintenance process. Keeping the token database clean will significantly improve the reliability of your push notification delivery.

2. Silent push throttling by iOS

Silent push notifications allow apps to refresh data in the background without showing an alert. They are commonly used to sync messages, update badges, or prepare content before the user opens the app.

Unlike standard notifications however, silent pushes are not guaranteed to run.

iOS dynamically throttles background notifications to protect battery life, network usage, and overall device performance. When this happens, the system may delay or skip background execution even if the push was successfully accepted by APNs.

Typical production symptom

The backend sends silent pushes successfully, but many devices never trigger the background callback.

For example, an app may send 10 background notifications but only receive 3–5 didReceiveRemoteNotification callbacks on the device.

From the backend perspective everything appears successful because APNs accepted the request, yet the device never performs the background task.

Common causes

Silent push throttling typically occurs when:

  • Too many silent pushes are sent in a short period.
  • The app has not been opened recently by the user.
  • Background tasks take too long to complete.
  • The completion handler is not called properly.
  • The device is in low power mode or has poor connectivity.

Recommended implementation

Silent pushes should be treated as best-effort background signals, not guaranteed delivery.

GuidelinePractical implementation
Keep background work shortFinish processing quickly and avoid heavy network requests
Always call the completion handlerEnsure fetchCompletionHandler runs after background work finishes
Reduce push frequencyBatch updates instead of sending many silent pushes
Combine with background fetchUse scheduled background fetch as a fallback sync mechanism
Track execution on real devicesLog when didReceiveRemoteNotification runs to monitor throttling

Reliable systems assume silent pushes may be delayed or dropped, and design synchronization flows accordingly.

3. Limited delivery observability after APNs acceptance

When a backend sends a push notification, APNs only confirms that the request was accepted for delivery. It does not confirm whether the notification actually reached the device.

After acceptance, delivery depends on several factors outside the backend’s control. These include device connectivity, OS behavior, and notification handling inside the app.

Because of this architecture, push systems often lack end-to-end delivery visibility.

Typical production symptom

The push infrastructure appears healthy, yet real user behavior suggests notifications are missing.

Typical signs include:

  • APNs responses return 200 Success.
  • Campaign metrics show lower-than-expected engagement.
  • Support tickets report missing notifications.
  • Delivery metrics cannot explain the gap.

From the backend perspective the push request succeeded, making the problem difficult to diagnose without device-side instrumentation.

Common causes

Delivery observability gaps usually occur because:

  • APNs do not confirm device-level delivery.
  • Devices may be offline when the push is sent.
  • iOS may delay or suppress notifications.
  • The app never logs when a push is received on the device.
  • Analytics systems only track push opens, not delivery events.

Without client-side instrumentation, it becomes impossible to determine where notifications fail.

Recommended implementation

Reliable push systems add device-level event tracking to observe the full notification lifecycle.

GuidelinePractical implementation
Track push received eventsLog when the notification arrives on the device
Track push opened eventsCapture when the user taps the notification
Attach campaign identifiersInclude a campaign_id or push_id in the payload
Log client-side failuresRecord errors when deep links or handlers fail
Monitor delivery vs engagementCompare sent, received, and opened metrics

Adding these signals allows teams to trace what happens after APNs accept the request and identify real delivery or handling issues in production.

When investigating missing notifications, device logs from real user sessions become essential.

This may be a good time to quickly mention our own tool, Bugfender. It allows developers to inspect client-side logs, push payloads, and notification handling directly from production devices without requiring users to connect to Xcode. Want to try it out? Start your free trial here.

4. Deep link routing failures after a push tap

Push notifications often include deep links that open a specific screen in the app. This is essential for many use cases such as messages, bookings, or product pages.

Deep linking becomes fragile at scale. Push notifications may open the app correctly, but fail to navigate to the intended screen due to routing errors, outdated parameters, or missing data.

Because the push itself appears successful, these failures can remain unnoticed while silently hurting conversion rates.

Typical production symptom

Users tap the notification, but the app does not open the expected content.

Common signs include:

  • The app opens on the home screen instead of the target page.
  • Users see empty or loading screens.
  • The deep-linked content no longer exists.
  • Conversion rates drop even though push open rates remain stable.

From the analytics perspective, the push appears successful because the notification was opened.

Common causes

Deep link failures usually occur because:

  • The deep link route is incorrect or outdated.
  • The payload contains missing or invalid identifiers.
  • The app version receiving the push does not support the route.
  • Required data has not finished loading when navigation occurs.
  • The app’s cold-start flow interrupts deep link routing.

In large apps with many screens and feature updates, these inconsistencies become common.

Recommended implementation

Push-triggered navigation should be designed as a resilient routing flow, not a direct screen jump.

GuidelinePractical implementation
Validate deep link parametersEnsure identifiers such as message_id or product_id exist before navigating
Implement route fallbacksIf the target screen fails, redirect to a safe parent screen instead of showing a blank page
Delay navigation until data is readyWait for API responses or local cache before opening the destination screen
Version-safe routingIgnore unsupported routes on older app versions
Log deep link executionTrack route, parameters, and navigation success for debugging

A reliable approach is to treat push navigation as a two-step process: open the app first, then resolve the destination once the app state and required data are ready.

This prevents broken navigation flows and ensures push notifications lead users to the correct content.

5. APNs throughput or queue bottlenecks

As push volume increases, the backend infrastructure sending notifications can become a bottleneck. Large campaigns or real-time notification bursts may overwhelm sending workers, queues, or network connections to APNs.

When this happens, notifications are still delivered but with significant delays. Time-sensitive messages such as reminders, bookings, or security alerts lose effectiveness if they arrive even a few minutes late.

Throughput limitations are often invisible in small test environments but when we’re sending hundreds of thousands or millions of notifications, they become critical.

Typical production symptom

Push notifications are eventually delivered, but much later than expected.

Common signs include:

  • Notifications arriving several minutes after the event.
  • Spikes in push sending latency during large campaigns.
  • Backend queues growing rapidly during broadcast sends.
  • Some pushes being dropped or retried due to timeouts.

From the backend perspective pushes are still sent successfully, but delivery timing becomes unreliable.

Common causes

Throughput bottlenecks usually occur because:

  • Push requests are sent sequentially instead of in parallel.
  • The backend opens too few HTTP/2 connections to APNs.
  • Sending workers cannot process the queue fast enough.
  • Broadcast campaigns generate sudden traffic spikes.
  • Retry logic overloads the queue during temporary failures.

Without proper scaling, push infrastructure can struggle to keep up with large send volumes.

Recommended implementation

Reliable push systems use parallelized delivery pipelines designed for high throughput.

GuidelinePractical implementation
Use multiple persistent HTTP/2 connectionsMaintain several open connections to APNs instead of reconnecting for every push
Parallelize push workersSend notifications concurrently using worker pools
Queue pushes asynchronouslyUse message queues (Kafka, RabbitMQ, or similar) to buffer spikes
Rate-limit broadcast campaignsSend large campaigns in controlled batches instead of one massive burst
Monitor delivery latencyTrack the time between event creation and push send completion

A scalable architecture separates event generation, queueing, and push delivery, allowing each stage to scale independently as the user base grows.

6. Push payload incompatibility across app versions

Push notification payloads often evolve as the app grows. New features introduce additional fields, deep links, or actions in the notification payload. Over time, different versions of the app may expect different payload structures.

If the backend sends a payload designed for the latest version of the app, older versions may not know how to handle it. This can cause broken deep links, missing UI elements, or even crashes when the notification is processed.

Because mobile users update apps gradually, production systems must handle multiple payload formats simultaneously.

Typical production symptom

Push notifications arrive on the device, but the app fails to process them correctly .

Common signs include:

  • The notification opens the wrong screen.
  • The app ignores the notification payload.
  • Interactive actions do not appear.
  • Crashes occur when parsing notification data.

These issues usually affect only a subset of users, typically those running older versions of the app.

Common causes

Payload incompatibility usually occurs because:

  • New payload fields were added without backward compatibility.
  • Older app versions expect different key names or structures.
  • New deep link routes do not exist in older builds.
  • Interactive notification categories were introduced later.
  • Payload validation is missing on the client side.

As apps evolve, these mismatches become more frequent unless payload design is version-aware.

Recommended implementation

Push payloads should be designed as backward-compatible contracts between the backend and multiple app versions.

GuidelinePractical implementation
Use optional payload fieldsNew fields should not break parsing in older app versions
Version payload structuresInclude a payload_version field so the app can handle different formats
Maintain backward-compatible keysAvoid renaming or removing keys used by older clients
Validate payloads on the clientSafely parse notification data and ignore unknown fields
Roll out new payload features graduallyEnsure older versions still function before enabling new behaviors

It’s generally good practice to treat push payloads like public APIs. Once deployed, they must remain stable enough for older clients until those versions naturally phase out.

7. Notification Service Extension failures

Rich push notifications allow apps to modify the notification before it appears. This is typically used to download images, decrypt content, or modify the notification text using a Notification Service Extension.

The extension runs in a separate process and has strict execution limits. If it fails, iOS may fall back to the original notification or display nothing at all.

Because the extension executes silently in the background, these failures often go unnoticed in testing but appear in real-world conditions such as slow networks or large media files.

Typical production symptom

Notifications arrive but rich content is missing or inconsistent.

Common signs include:

  • Image attachments sometimes fail to appear.
  • Notifications display only the fallback text.
  • Different devices show different notification formats.
  • Rich notifications work on Wi-Fi but fail on mobile networks.

From the user perspective, the notification looks unreliable or partially broken.

Common causes

Service extension failures usually occur because:

  • The media file is simply too large to download in time.
  • The extension exceeds the execution time limit (≈30 seconds).
  • The download fails due to network latency.
  • The extension crashes while processing the payload.
  • The app fails to call the completion handler before timeout.

When the extension fails, iOS may display the original notification or skip the modification entirely.

Recommended implementation

Rich notification extensions should be designed to fail gracefully and complete quickly.

GuidelinePractical implementation
Keep media lightweightPrefer compressed images under a few hundred KB
Implement download timeoutsCancel downloads if they exceed a short time window
Provide fallback contentEnsure the notification still makes sense without media
Always call the completion handlerReturn the best attempt content before the system timeout
Log extension failuresTrack errors and timeouts to diagnose production issues

A reliable extension treats media and enhancements as optional improvements, not required elements for the notification to function correctly.

8. Incorrect collapse identifiers replacing messages

APNs supports collapse identifiers to prevent sending multiple similar notifications to the same device. When several pushes share the same collapse-id, iOS keeps only the most recent one and discards the others.

This mechanism is useful for updates like live scores, delivery tracking, or message counters. However, incorrect configuration can cause important notifications to be silently replaced before the user ever sees them.

Because APNs processes the requests successfully, these losses can remain invisible in backend metrics.

Typical production symptom

Notifications appear to be missing or randomly replaced on the device.

Common signs include:

  • Users receive only the latest notification in a sequence.
  • Intermediate notifications never appear.
  • Message threads skip updates.
  • Push analytics show sends, but users report fewer notifications.

From the backend perspective, all pushes were delivered successfully. But this is obviously misleading.

Common causes

Collapse-related issues usually occur because:

  • Multiple notifications share the same collapse-id unintentionally.
  • Collapse IDs are reused across unrelated notification types.
  • Broadcast campaigns use identical collapse identifiers.
  • Updates are sent too frequently with the same collapse key.
  • Backend logic generates static collapse identifiers instead of contextual ones.

In these situations, newer pushes can overwrite earlier ones before they reach the user.

Recommended implementation

Collapse identifiers should be used only for updates that intentionally replace previous notifications.

GuidelinePractical implementation
Use collapse IDs only for replaceable updatesExamples: live scores, delivery status, or progress updates
Generate contextual identifiersUse identifiers tied to a specific resource such as order_123_status
Avoid global collapse IDsNever reuse the same collapse key for different notification categories
Separate transactional notificationsCritical notifications (OTP, alerts, confirmations) should not use collapse IDs
Test burst scenariosSimulate multiple notifications sent within seconds to verify correct behavior

When used correctly, collapse identifiers reduce notification noise. When misconfigured, they silently remove messages that users were supposed to see.

9. Notification ordering issues during retries

Push systems often include retry mechanisms to recover from temporary failures such as network errors, timeouts, or backend overload. While retries improve reliability, they can introduce ordering problems when multiple notifications are sent for the same user.

If an earlier notification fails and is retried later, it may arrive after a newer notification. This can confuse users, especially when messages represent sequential events such as chat messages, status updates, or transaction steps.

Because APNs processes pushes independently, it does not guarantee strict ordering between notifications.

Typical production symptom

Users receive notifications in the wrong sequence.

Common signs include:

  • an earlier message arriving after a newer one
  • status updates appearing in the wrong order
  • conversation notifications showing inconsistent timelines
  • delivery confirmations appearing before the original event

These issues usually appear intermittently and are difficult to reproduce in testing.

Common causes

Ordering issues typically occur because:

  • retry queues resend failed pushes later than intended
  • multiple push workers send notifications concurrently
  • backend events are processed out of order
  • the retry mechanism does not preserve original timestamps
  • notifications are queued in different infrastructure layers

When several systems generate pushes simultaneously, maintaining correct order becomes more difficult.

Recommended implementation

Push pipelines should include safeguards to maintain logical ordering for related notifications.

GuidelinePractical implementation
Attach event timestampsInclude a timestamp or sequence number in the payload
Implement ordering checksIgnore outdated notifications if a newer event already occurred
Preserve event order in queuesEnsure retries do not bypass earlier queued notifications
Use collapse identifiers for updatesReplace outdated status updates with the newest one
Separate critical notificationsAvoid retry delays for time-sensitive transactional pushes

Designing push notifications as state updates instead of isolated events helps prevent confusion when retries or network delays affect delivery timing.

10. Long-term notification permission decay

Even when users initially allow push notifications, permission rates tend to decline over time. Users disable notifications in system settings when they feel overwhelmed, receive irrelevant alerts, or stop using the app regularly.

Unlike delivery or infrastructure issues, this problem occurs at the user behavior level. The push system may work perfectly, but the reachable audience gradually shrinks.

Because permission changes happen outside the app, many teams underestimate how quickly their addressable push audience decays.

Typical production symptom

Push campaigns appear to perform worse over time, even though the infrastructure and targeting remain unchanged.

Common signs include:

  • the percentage of users reachable by push steadily decreases
  • long-term users stop receiving notifications
  • reactivation campaigns reach fewer inactive users
  • push engagement drops despite stable message quality

From the backend perspective, pushes are still sent successfully, but the number of eligible devices declines.

Common causes

Permission decay usually occurs because:

  • users disable notifications in system settings
  • apps send too many non-essential notifications
  • notifications feel repetitive or irrelevant
  • inactive users stop interacting with the app
  • the app never re-checks notification permission status

Over time, these behaviors gradually reduce the portion of users that can receive pushes.

Recommended implementation

Apps should actively monitor and manage notification permissions to maintain a healthy push audience.

GuidelinePractical implementation
Track notification permission statusPeriodically check UNUserNotificationCenter authorization status
Measure reachable push audienceMonitor the percentage of active users who can receive notifications
Reduce unnecessary pushesAvoid sending frequent or low-value alerts
Segment inactive users carefullyLimit reactivation pushes to small, controlled experiments
Educate users in-appShow contextual prompts explaining the value of notifications

Sustainable push strategies focus on relevance and restraint. Protecting user trust is essential to keeping long-term notification permissions enabled.

Making iOS push notifications reliable in production

Push notifications often work perfectly during development but behave differently once apps scale to thousands or millions of devices.

Most production issues do not come from APNs itself, but from surrounding systems such as device token management, payload compatibility, backend queues, or deep link routing.

Building reliable push infrastructure requires treating push notifications as a distributed system, with proper monitoring, token lifecycle management, and scalable delivery pipelines.

With the right architecture and device-level observability, teams can diagnose delivery problems early and maintain stable push notification systems in real production environments.

FAQs about advanced iOS push notifications

How many push notifications can iOS apps send per second?

Apple does not publish strict rate limits for APNs. In practice, throughput depends on your infrastructure and the number of parallel HTTP/2 connections to APNs. Large systems typically send notifications using multiple persistent connections and worker pools so pushes can be delivered concurrently. If notifications are sent sequentially or through too few connections, large campaigns can introduce noticeable delivery delays.

Do iOS push notifications work when the device is offline?

If the device is temporarily offline, APNs may store the notification and attempt delivery once the device reconnects. However, this behavior depends on the notification expiration time and system conditions. If a newer notification replaces an older one or the expiration time has passed, the original push may never be delivered. For time-sensitive messages, it is recommended to set an appropriate expiration timestamp.

How can I test push notifications at scale?

Testing push notifications across thousands of devices requires more than manual testing. Teams typically run internal staging campaigns, simulate high-volume sends, log push lifecycle events such as received, opened, and converted, and monitor delivery latency in production. Many reliability issues only appear under real device conditions and high traffic.

Can iOS push notifications wake the app in the background?

Yes, silent push notifications can wake the app to perform background work when the payload contains content-available: 1. However, execution is not guaranteed. iOS may delay or skip background processing depending on battery state, device usage patterns, or system resource limits. For this reason, silent pushes should be treated as best-effort background signals rather than guaranteed triggers.

What is the maximum payload size for APNs?

APNs supports a maximum payload size of 4 KB (4096 bytes). If a push payload exceeds this limit, APNs rejects the request. To avoid issues, payloads should contain only essential data while additional content is retrieved from the server after the app opens.

Can push notifications trigger app crashes?

Push notifications themselves do not crash the device, but the code handling the payload inside the app can. Crashes may occur if the app attempts to parse unexpected payload fields, navigate to unsupported routes, or access data that is not available yet. Defensive parsing and payload validation help prevent these runtime issues.

Should push notification logic live in the backend or the app?

Most push logic should live in the backend, where segmentation, scheduling, and delivery pipelines can scale independently from the mobile client. The app should primarily handle token registration, payload parsing, deep link routing, and notification lifecycle logging. This separation helps maintain reliability as the system grows.

Expect The Unexpected!

Debug Faster With Bugfender

Start for Free
blog author

Aleix Ventayol

Aleix Ventayol is CEO and co-founder of Bugfender, with 20 years' experience building apps and solutions for clients like AVG, Qustodio, Primavera Sound and Levi's. As a former CTO and full-stack developer, Aleix is passionate about building tools that solve the real problems of app development and help teams build better software.

Join thousands of developers
and start fixing bugs faster than ever.