Thanks so much, @tbartelmess1—this is super helpful, and really appreciated
a bit more context from our app:
App context (what we store)
The blobs we persist will be user-generated cruise photos, we would downsize those to more manageable size as iphone format photos can be quite big, but they would still be in the 1-3 mb after downsizing
Realistic volume per active user: a few hundred images/year; heavy users could reach low thousands over time.
Decision: use Core Data Binary Data + “Allows External Storage”
We’ll keep originals as Binary Data (Allows External Storage) so Core Data handles externalization transparently, my philosophy has always been to offload as much work to the system services as possible.
We’ll keep thumbnails as well inline in coredata (let coredata decide but likely will be inline (blob)).
CloudKit mirroring
We’ll rely on NSPersistentCloudKitContainer mirroring; we understand CloudKit decides when an attribute becomes a CKAsset independently of Core Data’s externalization threshold. That’s fine for us.
Practical assumption: for us, the full binary will still transfer when needed as part of the asset, so our bandwidth/latency plan is to (a) compress originals to HEIC/JPEG on-save, (b) show thumbnails first, (c) lazy-load the full image only on demand.
Low-disk behavior
We’ll provide a user-visible “Free up space” control that:
Safely deletes locally cached display sizes if space is low (thumbnails kept).
Leaves Core Data records intact so we can re-hydrate from CloudKit when needed.
For memory, we’ll downsample on decode and avoid loading multiple full-res images simultaneously.
Why not manual URLs again?
We originally tried manual file URLs to keep the SQLite file tiny, but post-update brittleness and sync edge cases crept in (missing files, path changes, race conditions). Using Core Data + CloudKit’s native path feels safer.
Thanks again for the clear pointers and links. Your note about memory and disk-pressure tradeoffs was a missing piece—splitting thumbnails/originals and letting Core Data + CloudKit do their thing looks like the right balance for us.
— Paul