Beware, CKShare can only be used to share a few hundred records

Hi,


We had encountered an issue saving a CKShare which uses a larger parent hierarchy of more than 5.000 records (see https://forums.developer.apple.com/thread/64194)


Sadly, we just received an answer from the (very helpful and responsive) Apple Developer Technical Support that CKShare is currently only designed to share a few hundred records. The hard limit seems to be 5.000 records when creating a CKShare, the recommendation is 200.


Be sure to design your apps with these limits in mind when you're planning to use CKShare. It would be great if anyone with a real-world usecase for an app can file a feature request (http://bugreport.apple.com). Mine is #28548349.

Replies

@MendelK: Just to confirm, despite the guidance, you were able to share greater numbers of records as long as you created the CKShare before inserting all of the records?


Were you able to alter the CKShare (add/remove participants) in this case, after you added all of the records?

Sharing works with hundreds of thousands of records in our test environment but only if you create the CKShare before creating this many child records to the parent record.


But this does not seem to be a Apple-sanctioned way - you should create a share shortly before you invite the first CKParticipant to the share. In this case, the CKShare can only be created if 5.000 or less records are assigned to the root record (it does not seem to matter if the parent/child relationships are a hierarchy or just a flat list with a parent records and 5.000 childs).


We could add or remove participants and other users were able to accept the CKShare.


It seems that the 5.000 records is the hard limit when creating the CKShare. Adding the records afterwards currently works but it is up to Apple when or if a limit will be enforced. Sadly, we got no word on that.


We are, too, desperately looking for a workaround. 😟 Please make sure that you are creating a feature request for this issue: https://bugreport.apple.com

Thanks for bringing attention of other developers to this problem.


Undisclosed limitations is becoming a very bad pattern for CloudKit. First they forgot to mention that you can't have more than 750 records referenced with a self delete rule to single record, now there is limitation for sharing which they also did not disclose.


Created radar 28627971.

Speculating, CloudKit hits these limits (creating a CKShare, resolving delete rules) where one operation affects a large number of records at once.

Most likely that is the case. Still, it is absolutely necessary to disclose limits like that.


Although I have to say that the self delete references limit is pretty useless for limiting server load. You can always create a nested hierarcy of records with this reference and after the root record is deleted, the server will still have to delete far more than 750 records at once.

Maybe CloudKit can delete a hierarchy more efficiently than they can delete a single record with many childs and a cascade rule. It could be that they split up the hierarchy of cascade-deletes into multiple single deletes.


Interestingly, a hierarchy of child/parent records does not seem to work more efficiently when creating a CKShare: It does not matter of all childs are assigned to a single root record or if a real deep hierarchy exists. The total count of records that are attached to a CKShare seems to matter.

Regarding "Adding the records afterwards currently works..." I have hit on another problem that could be related. Once you remove the last participant from a share, the CKShare is also automatically deleted. In this case can one recreate the share if more than 5000 records were originally attached to it.

This can be circumvented by NOT using the normal NSSharingService panel.


We opted to distribute records evenly to multiple CKZones to get around this limation. Much work and bookkeeping but you can totally masquerade the issue from users.

Hopefully, Apple will one day resolve this limit.

So the problem is still there in iOS11?

It has nothing to do with a macOS or iOS release - it is a server-side limitation.

Thanks; and you're saying the limitation is still there, even though it's been a year since it was brought up?


If possible, can you also share some detials about the work-around you took: "We opted to distribute records evenly to multiple CKZones to get around this limation. Much work and bookkeeping but you can totally masquerade the issue from users."


Do you mean you keep like 4000 records in a shared zone, and then create new (shared) ones as needed? So the limitation is per-zone, not per database?

Also. does not using the NSSharingService panel mean that this issue is completely avoided? If so, why do you need to create new zones for this?


I'm currently reconsidering whether to contiue to use CloudKit or go for some other server, based on this problem specifically, and your input would be really appreciated.

Yes, the limit is still present.


Two approaches:


1) Create new zones as needed - you need to create new CKShares and make other clients aware of the new zones (for example, using share URLs in the first shared zone that all users are aware of.

2) Create a fixed set of zones and distribute the records by record type (Type A goes to Zone A) - this way, you can share more records but the limit is not totally avoided


You cannot use the sharing service to create this kind of architecture. You need to do it on your own. Both options are rather complex to develop with much book-keeping, workarounds and testing involved - we spend around two months developing and testing only that part of our CloudKit sync.

Thanks a lot for this input! Just a couple more follow-ups:


- you mentioned earlier that the problem could be avoided if you didn't include 5000+ records in the share... so would something like this work:

a) when a new 'share' is created, create a new shared zone with a basic single record,

b) the 'sharer' shares the link to this zone

c) once the user accepts the 'share', the app can write all the records from the original zone into the 'shared' zone

d) everything from then on just reads and writes from the 'shared' zone, and people can be added/removed from the share without a problem


Doing this would avoid all the overhead with creating new zones as needed, or using a fixed set of zones (which wouldn't work in my case). The only question is, in your experience, would this even work? Did you consider this as an option?


- you said you "cannot use the sharing service to create this kind of architecture" .... you mean the UICloudSharing / NSSharingService API, right?

This WOULD work since when a zone has initially say 4999 records to share, you can continue to add records to the shared zone and it currently works. BUT it might break when Apple enforces the 5.000 limit and then you would be screwed with no possible workaround. I would not and have not taken the risk.


Second question: Yes, I meant the user interface classes.

Maybe a coincidence, but I notice that shared albums are limited to 5,000 photos & videos in iCloud Photo Library. So it seems Apple is abiding by the same limit.


https://support.apple.com/en-us/HT202299