Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Local Push Connectivity - Unreliable Connection

Hi! My project has the Local Push Connectivity entitlement for a feature we have requiring us to send low-latency critical notifications over a local, private Wi-Fi network.

We have our NEAppPushProvider creating a SSE connection using the Network framework with our hardware running a server. The server sends a keep-alive message every second. On an iPhone 16 with iOS 18+, the connection is reliable and remains stable for hours, regardless of whether the iOS app is in the foreground, background, or killed.

One of our QA engineers has been testing on an iPhone 13 running iOS 16, and has notice shortly after locking the phone, specifically when not connected to power the device seems to turn off the Wi-Fi radio. So when the server sends a notification, it is not received. About 30s later, it seems to be back on. This happens on regular intervals.

When looking at our log data, the provider does seem to be getting stopped, then restarted shortly after. The reason code is NEProviderStopReasonNoNetworkAvailable, which further validates that the network is getting dropped by the device in regular intervals.

My questions are:

  1. Were there possibly silent changes to the framework between iOS versions that could be the reason we're seeing inconsistent behavior?
  2. Is there a connection type we could use, instead of SSE, that would prevent the device from disconnecting and reconnecting to the Wi-Fi network?
  3. Is there an alternative approach to allow us to maintain a persistent network connection with the extension or app?

Observing this too. Unclear what's happening.

First off, I need to start with a general warning/comment. I've been supporting our voip APIs since iOS 4 and, across that time, there is one lesson I've seen OVER and OVER again:

WiFi network are terrible.

More specifically:

  1. Many "basic" WiFi network (like home WiFi routers with a single AP) have significant issues (for example, double NAT) which the user is unaware of because they don't effect things web browsing.

  2. Large scale network have exactly the same problem, except they also have serious issues with coverage gaps and/or lower level configuration issue that don't come up in #1.

Understanding this reality is critical because the other lesson I've learned is that "socket based voip" (our old voip sockets and now NEAppPushProvider) only work well on high quality networks. Note that this reality is what directly lead to PushKit, as the biggest reliability benefit PushKit provides is that push delivery over cellular makes it more likely that the push will reach the device.

Next, I need to comment on this:

The server sends a keep-alive message every second.

Again, my experience has been:

  • On a properly configured network where "everything" works, this kind of frequency is totally unnecessary. The network should be able to keep an idle connection "live" for minutes or even hours.

  • On a network that has problems, it's only marginally helpful, if at all.

My questions are:

Were there possibly silent changes to the framework between iOS versions that could be the reason we're seeing inconsistent behavior?

This isn't a framework issue as such. NEAppPushProvider's underlying implementation isn't all that complicated- check the SSID when joining the network, launch the app extension if it matches. All of the complexity here is in the network and driver stack underneath it.

Lots of stuff obviously change across the broader system, so I also can't say that system doesn't have any role here. However, what I can say is:

  • I'm not aware of any specific bug/issue with the iPhone 13 that would match what you're describing.

  • I'm not aware of any issue* with iOS 16 that would match what you're describing.

*One small exception to that. While looking into this, I did find one bug from iOS 16 about use disassociating at lock from AP with an internetworking IE configuration that indicates it's a battery powered hotspot. If that's what you're specifically testing with, then that might be a factor here.

Is there a connection type we could use, instead of SSE, that would prevent the device from disconnecting and reconnecting to the Wi-Fi network?

No, I wouldn't expect that to make any difference. You're already communicating once per second so as far the device is concerned that's an active connection. There isn't any way to be "more" active, and I suspect the actual issue here is much lower in the network stack.

Is there an alternative approach to allow us to maintain a persistent network connection with the extension or app?

Unfortunately, the place to start here is with the network, not the device.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

There are no issues if the device is unlocked and/or plugged into power, which led us to believe that the connection is dropped due to the system falling asleep. Connection to other things like Console.app log streaming seems to be dropped as well.

By the way, these devices only have Wi-fi enabled and no cellular (no SIM attached). Could that also have something to do with this situation? And are there anything useful to pull out from the device logs that can help us with this?

Thanks in advance,

We’ve noticed brief connection drops only after an iPhone has been locked and asleep for a while—almost as if the Wi-Fi radio powers down and the access point simply queues traffic until the device wakes. When the phone is unlocked, the connection remains solid.

Our use-case requires the link to stay alive continuously, even during extended sleep. Are there any iOS settings (or other device-level options) that can keep Wi-Fi awake under all circumstances?

Beyond Wi-Fi configuration itself, are there iPhone- or iOS-specific factors that might influence connection stability while the device is locked? We don’t see the same behaviour on Android handsets connected to the exact same network.

By the way, these devices only have Wi-fi enabled and no cellular (no SIM attached).

Yes, that's the scenario that tends to have the most problems.

Could that also have something to do with this situation?

Only indirectly. Having an active cellular radio tends to mask these issues by hiding WiFi issues.

And are there anything useful to pull out from the device logs that can help us with this?

The word "anything" is what's tricky there. Yes, I've definitely seen cases were sysdiagnose data helped identify and resolve issues. The problem is that this is true simply because the sysdiagnose provides a highly detailed "window" into exactly what's happening on the device, not because it provides a clear/quick/easy answer.

What I can't provide is a detailed guide to what you should look for or a systemic approach to this kind of investigation.

Our use-case requires the link to stay alive continuously, even during extended sleep. Are there any iOS settings (or other device-level options) that can keep Wi-Fi awake under all circumstances?

No, not that I'm aware of.

Beyond Wi-Fi configuration itself, are there iPhone- or iOS-specific factors that might influence connection stability while the device is locked?

No, nothing I can specifically point to.

However, there is one point I do want to comment on from the original post:

One of our QA engineers has been testing on an iPhone 13 running iOS 16

How well "WiFi-only" device/apps work definitely varies between iOS releases. If this particular use case is critical to your product, my recommendations are:

  • Limit your supported hardware/system range to something you can proactively validate and continually test. There may vary well be system versions and/or devices that simply aren't reliable and the best answer for those cases may simply be to not support them at all.

  • Focus that testing on new/future release, not just shipping system. Whenever possible, devices should not be upgraded until that particular device/system configuration has been validated.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Local Push Connectivity - Unreliable Connection
 
 
Q