How to upload large videos with PHAssetResourceUploadJobChangeRequest?

I'm implementing a PHBackgroundResourceUploadExtension to back up photos and videos from the user's library to our cloud storage service.

Our existing upload infrastructure uses chunked uploads for large files (splitting videos into smaller byte ranges and uploading each chunk separately). This approach:

  • Allows resumable uploads if interrupted
  • Stays within server-side request size limits
  • Provides granular progress tracking

Looking at the PHAssetResourceUploadJobChangeRequest.createJob(destination:resource:) API, I don't see a way to specify byte ranges or create multiple jobs for chunks of the same resource.

Questions:

  1. Does the system handle large files (1GB+) automatically under the hood, or is there a recommended maximum file size for a single upload job?
  2. Is there a supported pattern for chunked/resumable uploads, or should the destination URL endpoint handle the entire file in one request?
  3. If our server requires chunked uploads (e.g., BITS protocol with CreateSession → Fragment → CloseSession), is this extension the right mechanism, or should we use a different approach for large videos?

Any guidance on best practices for large asset uploads would be greatly appreciated.

Environment: iOS 26, Xcode 18

Thanks for the post. I'm not an expert on that API, not even close to that, so I'm inviting other engineers to jump into this thread and provide their options on the 3 questions.

This is a PhotoKit upload asset for background process. As noted the extension processes uploads only while enabled. Disable the extension when a person signs out or disables cloud sync in your app.

https://developer.apple.com/documentation/PhotoKit/uploading-asset-resources-in-the-background

The PHAssetResourceUploadJobChangeRequest.createJob(destination:resource:) API is designed to hand off the entire upload process to a system daemon. Because the system daemon manages the network connection out-of-process (to preserve battery and allow the extension to be suspended or terminated), it imposes specific architectural constraints on how your backend must receive the data.

Here is the limitations are documented https://developer.apple.com/documentation/photos/phphotoserror-swift.struct/limitexceeded Are you hitting any?

I believe the primary purpose of this API is to handle massive files without loading them into your extension's memory. As far as I know and looking at the list of limitation on the previous link, there is no strict maximum file size imposed by the API itself; it is limited only by the device's network conditions and your server's timeout/size limits.

The createJob(destination:resource:) API performs a upload to the single destination URL you provide. Because the system daemon handles the upload while your extension is likely suspended, it cannot "call back" into your code to ask for the next byte range or the next URL for a chunk and that makes sense so takes care of the file without you providing the chunks.

If I understand the api correctly, if the connection drops, the connection will attempt to resume the upload using standard HTTP. At that point, your server must support standard HTTP resumable uploads. I posted something similar a few days ago, I’ll find it and post the links here.

This is all I know about the API. I would encourage you to use it and see if you hit any limitations from the documentation, but it seems straightforward.

Albert Pascual
  Worldwide Developer Relations.

Thanks for the detailed response, Albert.

Our server API has a strict payload limit of 250 MB per request. Because of this constraint, our existing upload infrastructure uses chunked uploads for large files — splitting videos into smaller byte ranges and uploading each chunk separately via the BITS protocol (CreateSession → Fragment → CloseSession).

However, I don't see any API surface in PHAssetResourceUploadJobChangeRequest to:

  • Specify byte ranges for partial uploads
  • Create multiple sequential jobs for chunks of the same resource
  • Provide a callback/delegate pattern for "give me the next upload destination"

Given that the system daemon handles uploads out-of-process (as you explained), it seems this API assumes the destination endpoint can accept the entire file in a single HTTP request.

My question then becomes: For services with server-side payload limits, is PHBackgroundResourceUploadExtension the wrong tool for the job? Should we instead:

  1. Continue using our existing NSURLSession background upload approach (where we control chunking)?
  2. Is there a roadmap consideration for chunked upload support in this API?

Any guidance from the team would be appreciated. We'd love to adopt this new API for its battery/lifecycle benefits, but the 250 MB server limit is a hard constraint we can't easily change.

Thanks for your reply. I only know how the API works based on the documentation, I’m not in IT and I do not know the limitations on your server side.

Because the upload is handed off to a system daemon to be performed out-of-process, the API is currently designed around a "fire-and-forget" model for a single HTTP request per resource. It assumes the destination endpoint can ingest the entire payload in one go. But for your description this is not correct?

I would suggest to open a conversation with the IT department for that server and if not changes can be done, I would recommend to another approach.

If backend changes are entirely off the table, sticking with your custom NSURLSession implementation is the right call.

Albert Pascual
  Worldwide Developer Relations.

Is it possible for an engineer from PhotoKit team to take a look at this question and provide guidance here?

How to upload large videos with PHAssetResourceUploadJobChangeRequest?
 
 
Q