BGContinuedProcessingTask expiring unpredictably

I've adopted the new BGContinuedProcessingTask in iOS 26, and it has mostly been working well in internal testing. However, in production I'm getting reports of the tasks failing when the app is put into the background.

A bit of info on what I'm doing: I need to download a large amount of data (around 250 files) and process these files as they come down. The size of the files can vary: for some tasks each file might be around 10MB. For other tasks, the files might be 40MB. The processing is relatively lightweight, but the volume of data means the task can potentially take over an hour on slower internet connections (up to 10GB of data).

I set the totalUnitCount based on the number of files to be downloaded, and I increment completedUnitCount each time a file is completed.

After some experimentation, I've found that smaller tasks (e.g. 3GB, 10MB per file) seem to be okay, but larger tasks (e.g. 10GB, 40MB per file) seem to fail, usually just a few seconds after the task is backgrounded (and without even opening any other apps). I think I've even observed a case where the task expired while the app was foregrounded!

I'm trying to understand what the rules are with BGContinuedProcessingTask and I can see at least four possibilities that might be relevant:

  1. Is it necessary to provide progress updates at some minimum rate? For my larger tasks, where each file is ~40MB, there might be 20 or 30 seconds between progress updates. Does this make it more likely that the task will be expired?
  2. For larger tasks, the total time to complete can be 60–90 mins on slower internet connections. Is there some maximum amount of time the task can run for? Does the system attempt some kind of estimate of the overall time to complete and expire the task on that basis?
  3. The processing on each file is relatively lightweight, so most of the time the async stream is awaiting the next file to come down. Does the OS monitor the intensity of workload and suspend the task if it appears to be idle?
  4. I've noticed that the task UI sometimes displays a message, something along the lines of "Do you want to continue this task?" with a "Continue" and "Stop" option. What happens if the user simply ignores or doesn't see this message? Even if I tap "Continue" the task still seems to fail sometimes.

I've read the docs and watched the WWDC video, but there's not a whole lot of information on the specific issues I mention above. It would be great to get some clarity on this, and I'd also appreciate any advice on alternative ways I could approach my specific use case.

Based on the response from the engineer over on this post, I looked at the Console logs for the dasd process and found this:

Task has not reported progress within expected cadence, marking stalled (time without update: -36.27811694145203)

Does -36 mean 36 seconds since the last update? That seems plausible given my situation. What cadence do I need to hit to satisfy the system?

Not sure what to do now. This limitation seems to make BGContinuedProcessingTask unsuitable for my use case, since the size of the downloaded files can vary, as can the speed of the user's connection.

I could try to feed in fake progress updates to keep the task alive. Or I could try to monitor the byte count of downloading files and use that as the basis for progress updates (however, my previous experience trying to pass the byte count from URLSessionDelegate through an async stream was a nightmare).

In any case, it would still be useful if someone from engineering could respond to my above queries, so that I can better understand if there might be other issues to contend with (not just the progress cadence).

BGContinuedProcessingTask expiring unpredictably
 
 
Q