Extreme increase in app storage size after enabling CloudKit

I have a SwiftData flashcard app which I am syncing with CloudKit using NSPersistentCloudKitContainer. While syncing itself is working perfectly, I have noticed a dramatic increase in the app size after enabling sync.

Specifically, without CloudKit, 15k flashcards results in the default.store file being about 4.5 MB. With CloudKit, default.store is about 67 MB. I have inspected the store and found that most of this increase is due to the ANSCKRECORDMETADATA table.

My question is, does implementing CloudKit normally cause this magnitude of increase in storage? If it doesn’t, is there something in my model, schema, implementation, etc. that could be causing it?

Below are two other posts describing a similar issue, but neither with a solution. I replied to the first one about a month ago. I then submitted this to Developer Technical Support, but was asked to post my question in the forums, so here it is.

Strange behavior with 100k+ records in NSPersistentCloudKitContainer

Huge increase in sqlite file size after adopting CloudKit

Answered by DTS Engineer in 871045022

When you use SwiftData + CloudKit, under the hood, the SwiftData framework converts SwiftData models to Core Data managed objects, and use NSPersistentCloudKitContainer to synchronize the objects with CloudKit.

NSPersistentCloudKitContainer mirrors each Core Data managed object to (at least) a CloudKit record (CKRecord), as described in Reading CloudKit Records for Core Data. To manage the internal state of the synchronization, it adds a few tables to the store, and the ANSCKRECORDMETADATA table is one of them, which is used to store the metadata of the CloudKit records. The metadata includes the system fields and encoded data of every CloudKit record, so yes, you can see that the size of table gets quite large.

The ANSCKRECORDMETADATA table is an internal data structure that NSPersistentCloudKitContainer creates and consumes. You can review the documentation mentioned above to make sure that your models are translated to CloudKit schema correctly, but other than that, I don't see any way that can reduce the size of the table.

The data in the ANSCKRECORDMETADATA table isn't synchronized to CloudKit, and so I don't expect that it has any impact on the CloudKit storage consumption. Other than the on-device store size, did you see any other issue related to the table? If yes, I’d suggest that you file a feedback report. As my colleague mentioned here, attaching a representative dataset and a reproducible test will be a great help for us to analyze the issue. If you have a feedback report, please share your report ID here.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Accepted Answer

When you use SwiftData + CloudKit, under the hood, the SwiftData framework converts SwiftData models to Core Data managed objects, and use NSPersistentCloudKitContainer to synchronize the objects with CloudKit.

NSPersistentCloudKitContainer mirrors each Core Data managed object to (at least) a CloudKit record (CKRecord), as described in Reading CloudKit Records for Core Data. To manage the internal state of the synchronization, it adds a few tables to the store, and the ANSCKRECORDMETADATA table is one of them, which is used to store the metadata of the CloudKit records. The metadata includes the system fields and encoded data of every CloudKit record, so yes, you can see that the size of table gets quite large.

The ANSCKRECORDMETADATA table is an internal data structure that NSPersistentCloudKitContainer creates and consumes. You can review the documentation mentioned above to make sure that your models are translated to CloudKit schema correctly, but other than that, I don't see any way that can reduce the size of the table.

The data in the ANSCKRECORDMETADATA table isn't synchronized to CloudKit, and so I don't expect that it has any impact on the CloudKit storage consumption. Other than the on-device store size, did you see any other issue related to the table? If yes, I’d suggest that you file a feedback report. As my colleague mentioned here, attaching a representative dataset and a reproducible test will be a great help for us to analyze the issue. If you have a feedback report, please share your report ID here.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Paying around ~4kb per record is about what we would expect for most CloudKit schemas.

Depending on the shape of your data it may be more efficient to sync the flashcards as an archived set of blobs to CloudKit. That would reduce the record overhead significantly but wouldn't be appropriate for data that changes frequently.

It would require using a separate store / entity graph for CloudKit sync and then unpacking the archived records in to a local-only store that holds the inflated cards. But that would reduce this file size / storage considerably.

Extreme increase in app storage size after enabling CloudKit
 
 
Q