Which storage capacity key should be used for offline video downloads: volumeAvailableCapacityKey or volumeAvailableCapacityForImportantUsageKey?

I’m trying to understand which storage capacity key is the correct one to use when deciding whether my app can start downloading offline video content.

I read the documentation here: https://developer.apple.com/documentation/foundation/checking-volume-storage-capacity

but I still don’t fully understand the intended usage difference between:

  • volumeAvailableCapacityKey
  • volumeAvailableCapacityForImportantUsageKey

My app allows users to download videos for offline viewing. These downloads may remain on the device for a long time (days or even months), so they are not just temporary cache files.

On one hand, this seems to match the description of “storing data based on a user request”, which suggests using volumeAvailableCapacityForImportantUsageKey.

On the other hand, my understanding is that this value may assume the system is willing to aggressively purge caches and reclaim space for this “important usage”. I’m worried this could lead to unexpected or unpleasant side effects for the user if my app relies on that space.

What confuses me even more is that the values are significantly different on my device:

  • iPhone Settings reports about 142 GB free
  • volumeAvailableCapacityKey returns only ~56 GB
  • volumeAvailableCapacityForImportantUsageKey returns ~132 GB

So my question is:

For an app that downloads videos for offline playback — where the user explicitly requested the download, but the content may stay on device for a long time — which value is the recommended one to use when deciding whether there is enough free space to start the download?

Should offline media downloads generally be treated as “important usage” in the sense intended by this API?

Answered by DTS Engineer in 888322022

I'll start with the short answer, then follow with more details:

Should offline media downloads generally be treated as “important usage” in the sense intended by this API?

Yes, you should be using "important". You might also look at the availability key, but mainly as a diagnostic tool to tweak your app’s behavior, not to fundamentally alter what you "do". For example, if you're downloading very large files very quickly, it's possible for you to be adding new important data to the device faster than the device can delete cache data, which will cause available to "spike" to a low value. If that happens, simply waiting for a little while may resolve the issue.

Similarly, if available and opportunistic are both "low" and your app stores large amounts of cached data, then you might want to delete your own cached data during/before you transfer in important data.

but I still don’t fully understand the intended usage difference between:

So, let me lay out the meaning of the three keys:

volumeAvailableCapacityKey-> This is "the truth". That is, how much free space the volume ACTUALLY has at any particular moment in time.

volumeAvailableCapacityForOpportunisticUsageKey-> This is the amount of space the system "thinks" is available to "cache stuff".

volumeAvailableCapacityForImportantUsageKey-> This is the amount of space the system "thinks" should be used to store actual user data.

Conceptually, the idea here is that the system will "fill up" currently unused space with cached data, then delete that data as needed by "important" usage. In technical terms, data the system can delete (like data stored in "Caches") or iCloud (because it's also stored in off-device) is considered "opportunistic", while everything else is considered "important".

That also means that this isn't really an issue:

On the other hand, my understanding is that this value may assume the system is willing to aggressively purge caches and reclaim space for this “important usage”. I’m worried this could lead to unexpected or unpleasant side effects for the user if my app relies on that space.

The practical definition of "opportunistic" is sufficiently narrow that this isn't data the user should ever be relying on. To put it bluntly, no app should be putting data the user "cares" about in "Caches".

Looking at your specific example:

volumeAvailableCapacityKey returns only ~56 GB

That's the actual state of the device currently.

volumeAvailableCapacityForImportantUsageKey returns ~132 GB

Most of that data (~76 GB) is cached data the system is perfectly happy to delete, so that's how much data it could store if it threw out most/all of its cached data.

iPhone Settings reports about 142 GB free

That's a number we're showing the user. I haven't looked at the EXACT of that calculation, but the system also maintains a bit of "extra" storage so that:

  • There's plenty of available storage for important usage to use while opportunistic data is being deleted.

  • There's some "extra" storage available to the user if/when the drive actually becomes "full" of important data.

...and I suspect that buffer is most of that ~10 GB.

Am I understanding correctly that as the device runs out of storage, the system has less reclaimable/purgeable space available, so the different capacity estimates start converging because there is simply less content that iPadOS can optimize or clean up automatically?

Yes, that's correct. More specifically, "availability" and "important" converge, while opportunistic goes to "0". There's some other nuance there in that the calculations are more complicated than they seem. The basic "available" number is easy, as the file system directly tracks its own "free" storage and we can just return that number. However, the problem with the other numbers is that it relies on determining how much space deleting an object will free, which is a trickier calculation than it seems.

Another interesting observation is that after reaching the values from Case 2, content downloads in many apps effectively stopped working.

Yes. Basically, "don't do that". The system operates as a database shared among "all" clients, and when it gets completely “full," that starts to break down. Your app should always ensure there's a significant "extra" buffer. Exactly how big that buffer should be depends on exactly what you're downloading and why, but I generally recommend at least 1 GB, and I would probably warn the user that space was becoming constrained while important got that "close".

One last comment on that last point. I would think very carefully about what size data you provide to the user and how you present it. If you present the number as a detailed, specific value, then:

  • Users will compare your number to Settings and other apps.

  • They will notice that it doesn't match and complain about it.

  • You will desperately try and make the values match.

...and that will continue until you eventually give up and do something else. The problem here is that you:

  • You don't have access to the exact calculation Settings.app is making.

  • Available storage fluctuates enough that even WITH the exact calculations, the numbers still wouldn't always match.

In my experience, the simplest solution to these issues is using your device’s state as an example, saying "100+ GB" is just as useful to the user, while sidestepping any comparison between your app and the rest of the system.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

I did some additional testing on my second device and noticed behavior that seems interesting, but I’m not sure whether I’m interpreting it correctly.

Case 1:

  • iPad Settings reports ~20 GB free
  • volumeAvailableCapacityKey returns ~7.6 GB
  • volumeAvailableCapacityForImportantUsageKey returns ~19.3 GB

Case 2 (after I intentionally downloaded a large amount of content to fill up the device storage):

  • iPad Settings reports ~215 MB free
  • volumeAvailableCapacityKey returns ~157 MB
  • volumeAvailableCapacityForImportantUsageKey returns ~197 MB

What surprised me is that in the first case, volumeAvailableCapacityForImportantUsageKey is very close to the value shown in Settings, while volumeAvailableCapacityKey is much lower.

But in the second case, when the device is almost full, all three values become much closer to each other.

Am I understanding correctly that as the device runs out of storage, the system has less reclaimable/purgeable space available, so the different capacity estimates start converging because there is simply less content that iPadOS can optimize or clean up automatically?

Another interesting observation is that after reaching the values from Case 2, content downloads in many apps effectively stopped working.

For example:

  • Netflix appeared to start downloading, but nothing actually happened
  • Some other apps with content downloading also stopped downloading videos without showing any error
  • App Store no longer allowed installing apps because of insufficient storage
  • Xcode once failed to install my app onto the device because there was not enough space available

What confuses me is that all of the reported values were still greater than zero.

At the same time, ~215 MB free space is the absolute minimum I managed to reach on the device, so perhaps iPadOS has some kind of internal storage reservation or minimum writable threshold that is not reflected directly in these APIs?

Accepted Answer

I'll start with the short answer, then follow with more details:

Should offline media downloads generally be treated as “important usage” in the sense intended by this API?

Yes, you should be using "important". You might also look at the availability key, but mainly as a diagnostic tool to tweak your app’s behavior, not to fundamentally alter what you "do". For example, if you're downloading very large files very quickly, it's possible for you to be adding new important data to the device faster than the device can delete cache data, which will cause available to "spike" to a low value. If that happens, simply waiting for a little while may resolve the issue.

Similarly, if available and opportunistic are both "low" and your app stores large amounts of cached data, then you might want to delete your own cached data during/before you transfer in important data.

but I still don’t fully understand the intended usage difference between:

So, let me lay out the meaning of the three keys:

volumeAvailableCapacityKey-> This is "the truth". That is, how much free space the volume ACTUALLY has at any particular moment in time.

volumeAvailableCapacityForOpportunisticUsageKey-> This is the amount of space the system "thinks" is available to "cache stuff".

volumeAvailableCapacityForImportantUsageKey-> This is the amount of space the system "thinks" should be used to store actual user data.

Conceptually, the idea here is that the system will "fill up" currently unused space with cached data, then delete that data as needed by "important" usage. In technical terms, data the system can delete (like data stored in "Caches") or iCloud (because it's also stored in off-device) is considered "opportunistic", while everything else is considered "important".

That also means that this isn't really an issue:

On the other hand, my understanding is that this value may assume the system is willing to aggressively purge caches and reclaim space for this “important usage”. I’m worried this could lead to unexpected or unpleasant side effects for the user if my app relies on that space.

The practical definition of "opportunistic" is sufficiently narrow that this isn't data the user should ever be relying on. To put it bluntly, no app should be putting data the user "cares" about in "Caches".

Looking at your specific example:

volumeAvailableCapacityKey returns only ~56 GB

That's the actual state of the device currently.

volumeAvailableCapacityForImportantUsageKey returns ~132 GB

Most of that data (~76 GB) is cached data the system is perfectly happy to delete, so that's how much data it could store if it threw out most/all of its cached data.

iPhone Settings reports about 142 GB free

That's a number we're showing the user. I haven't looked at the EXACT of that calculation, but the system also maintains a bit of "extra" storage so that:

  • There's plenty of available storage for important usage to use while opportunistic data is being deleted.

  • There's some "extra" storage available to the user if/when the drive actually becomes "full" of important data.

...and I suspect that buffer is most of that ~10 GB.

Am I understanding correctly that as the device runs out of storage, the system has less reclaimable/purgeable space available, so the different capacity estimates start converging because there is simply less content that iPadOS can optimize or clean up automatically?

Yes, that's correct. More specifically, "availability" and "important" converge, while opportunistic goes to "0". There's some other nuance there in that the calculations are more complicated than they seem. The basic "available" number is easy, as the file system directly tracks its own "free" storage and we can just return that number. However, the problem with the other numbers is that it relies on determining how much space deleting an object will free, which is a trickier calculation than it seems.

Another interesting observation is that after reaching the values from Case 2, content downloads in many apps effectively stopped working.

Yes. Basically, "don't do that". The system operates as a database shared among "all" clients, and when it gets completely “full," that starts to break down. Your app should always ensure there's a significant "extra" buffer. Exactly how big that buffer should be depends on exactly what you're downloading and why, but I generally recommend at least 1 GB, and I would probably warn the user that space was becoming constrained while important got that "close".

One last comment on that last point. I would think very carefully about what size data you provide to the user and how you present it. If you present the number as a detailed, specific value, then:

  • Users will compare your number to Settings and other apps.

  • They will notice that it doesn't match and complain about it.

  • You will desperately try and make the values match.

...and that will continue until you eventually give up and do something else. The problem here is that you:

  • You don't have access to the exact calculation Settings.app is making.

  • Available storage fluctuates enough that even WITH the exact calculations, the numbers still wouldn't always match.

In my experience, the simplest solution to these issues is using your device’s state as an example, saying "100+ GB" is just as useful to the user, while sidestepping any comparison between your app and the rest of the system.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

My concern was more about overall UX: caches still help apps across the system load faster and feel smoother. So I was wondering whether aggressively reclaiming cache space for “important” data could noticeably reduce the overall system experience, even if no important user data is lost.

Yes and no.

First off, the place to start here is that the basic starting point here is that many users will basically have a VAST amount of otherwise unused storage, which the system could use to store data that might conceivably improve their overall experience.

If you take your device as an example, the rough math of:

<important> - <available> -> <cached>

~132 GB - ~56 GB -> 76 GB

...which means you have at LEAST 60+ GB of cached "stuff" that the system would be perfectly willing to throw away if/when you actually needed that storage. Now, deleting some of that data would absolutely affect the overall user experience. In practice, most of that data is things like your photo or music library where having the data "at hand" is helpful, but the data is in the cloud so it could be deleted. However, that's still a LOT of data and it's VERY likely that large portions of it... you'd never really "miss".

Note: the examples that follow are to illustrate how the system generally behaves, not detailed explanations of specific behavior.

As the most obvious example, if the system discards the 100 pictures or songs with the oldest "looked at" date, odds are you'd never even notice. In a similar vein, a full live picture set can be quite large, so pruning that image set or deleting everything except the main image/thumbnail can recover large amounts of space. You'd never notice it was gone until you happened to dig into one of those images and it needed to be downloaded again.

One thing to note here is that I think the term "cache" is somewhat misleading here, as it creates the perception that this is purely about simple "performance caching". However, as the cloud data above shows, that's somewhat misleading. Putting that in more concrete terms, when you look at something like browser caching, there's a fairly low point of diminishing returns as you end up storing data the user never needs (because they never return to the site) or you end up having to download anyway (because enough time has passed that you can't trust the cache).

While some of that data is that kind of data, at this kind of size scale, what we're typically dealing with isn't about storing temporary data that might be reused, but is more managing which cloud user data is stored locally vs. remotely. It's real user data, it just doesn't necessarily HAVE to be on the device.

Finally, there's a big element here of "yes, but so what". Going back to the original goal, the point of all this was to take advantage of a resource that would otherwise have gone unused (large amounts of empty storage). If the user wants/needs to use that space to store "real" data then great, let’s do that!

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Which storage capacity key should be used for offline video downloads: volumeAvailableCapacityKey or volumeAvailableCapacityForImportantUsageKey?
 
 
Q