iOS BGProcessingTask + Background Upload Not Executing Reliably on TestFlight (Works in Debug)
Description: We are facing an issue with BGTaskScheduler and BGProcessingTask when trying to perform a background audio-upload flow on iOS. The behavior is inconsistent between Debug builds and TestFlight (Release) builds.
Summary of the Problem
Our application records long audio files (up to 1 hour) and triggers a background upload using:
BGTaskScheduler BGProcessingTaskRequest Background URLSession (background with identifier) URLSession background upload task + AppDelegate.handleEventsForBackgroundURLSession
In Debug mode (Xcode → Run on device), everything works as expected: BGProcessingTask executes handleEventsForBackgroundURLSession fires Background URLSession continues uploads reliably Long audio files successfully upload even when the app is in background or terminated
However, in TestFlight / Release mode, the system does not reliably launch the BGProcessingTask or Background URLSession events.
Technical Details We explicitly register BGTaskScheduler: BGTaskScheduler.shared.register( forTaskWithIdentifier: "example.background.process", using: nil ) { task in self.handleBackgroundProcessing(task: task as! BGProcessingTask) }
We schedule it using: let request = BGProcessingTaskRequest(identifier: "example.background.process") request.requiresNetworkConnectivity = true request.requiresExternalPower = false try BGTaskScheduler.shared.submit(request)
We also use Background URLSession: let config = URLSessionConfiguration.background(withIdentifier: sessionId) config.sessionSendsLaunchEvents = true config.isDiscretionary = false
AppDelegate.handleEventsForBackgroundURLSession is implemented correctly and works in Debug.
Issue Observed (TestFlight Only) In TestFlight builds:
BGProcessingTask rarely triggers, or the system marks it as NO LONGER RUNNING. Background upload tasks sometimes never start or complete. No logs appear from our BGProcessingTask handler. system logs show messages like:
NO LONGER RUNNING bgProcessing-example.background.process Tasks running in group [com.apple.dasd.defaultNetwork] are 1!
This occurs most frequently for large audio uploads (30–60 minutes), while small files behave normally.
What We Have Verified Proper Info.plist values: Permitted background modes: processing, audio, fetch BGTaskSchedulerPermittedIdentifiers contains our identifier BGProcessingTask is being submitted successfully (no errors) App has microphone permission + background audio works
Device plugged/unplugged doesn’t change outcome Key Question for Apple We need clarification on: Why BGProcessingTask behave differently between Debug and TestFlight builds?
Are there additional restrictions or heuristics (related to file size, CPU usage, runtime, network load, or power constraints) that cause BGProcessingTask to be throttled or skipped in Release/TestFlight?
How can we guarantee a background upload continues reliably for large files (100MB–500MB) on TestFlight and App Store builds?
Is there an Apple-recommended pattern to combine BGProcessingTask + Background URLSession for long-running uploads?
Expected Result
Background uploads should continue reliably for long audio files (>30 minutes) when the app goes to background or is terminated, in the same way they currently function in Debug builds.
You’re combining two background execution technologies — background tasks and URLSession background sessions — and its not clear why. When you use a background session, your app doesn’t need to run in the background for the transfer to make progress. Rather, a system process (currently nsurlsessiond) does the transfer on your behalf. Can you explain why you’ve add background tasks into the mix?
As to what’s going on with your current code, I have a bunch of debugging hints for you. First, you’ve not clearly separated your build configuration (Debug or Release) from your code signing (Apple Development or Apple Distribution for TestFlight). Teasing those apart can yield useful results, because it tells you whether the issue is with the way that your code is built or the way that it’s distributed. I talk about this in more depth in Isolating Code Signing Problems from Build Problems.
Second, you’re testing background code from Xcode. This can be useful in limitation circumstances, but it can also be very misleading. See Testing and Debugging Code Running in the Background for more about that.
Third, I have a specific version of that post for URLSession background session work: Testing Background Session Code.
Finally, you seem to have unrealistic expectations of the Background Tasks framework. Now, it might turn out that you don’t need that framework at all, but if you do you should read iOS Background Execution Limits.
Well, that’s certainly a lot for you to explore. Please play around with this and let me know how you get along.
ps It’d help if you formatted your code blocks as code. Your current post is very hard to read. See tip 5 in Quinn’s Top Ten DevForums Tips.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"