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.

How to upload large videos with PHAssetResourceUploadJobChangeRequest?
 
 
Q