DEV Community

Amol Srivastava
Amol Srivastava

Posted on

iCloud Key-Value Store vs CloudKit: A Decision Guide for Solo iOS Developers

Every local-first iOS app eventually hits the same question: the user has the app on their phone and their iPad, and they want their data on both. Apple gives you two very different tools for this, and picking the wrong one costs you a rewrite. Here's the actual decision, stripped of marketing language.

NSUbiquitousKeyValueStore: for settings, not data

NSUbiquitousKeyValueStore is the iCloud equivalent of UserDefaults — a small, syncing key-value dictionary, capped at 1MB total and 1024 keys. It syncs automatically, requires almost no setup beyond enabling the iCloud capability, and has no query API because it isn't a database. You get a dictionary that happens to sync.

let store = NSUbiquitousKeyValueStore.default
store.set(true, forKey: "hasSeenOnboarding")
store.synchronize()
Enter fullscreen mode Exit fullscreen mode

This is the right tool when what you're syncing is small, singular, and doesn't need to be queried — feature flags, a selected theme, the last-viewed tab, a handful of user preferences. It is emphatically the wrong tool the moment you're tempted to store an array of user-created objects in it, even a short one, because you'll hit the size ceiling faster than you expect and you'll have no way to sync partial updates — every write replaces the whole value for that key.

CloudKit: for actual data

CloudKit is a real database — records, record types, queries, relationships, subscriptions for push-based sync, and a private database scoped per user with no server code required on your end. The setup cost is real: you're defining a schema, thinking about CKRecord conflict resolution, and probably reaching for NSPersistentCloudKitContainer if you want Core Data to handle the sync plumbing for you.

let container = NSPersistentCloudKitContainer(name: "Model")
container.loadPersistentStores { _, error in
    if let error { fatalError("Unresolved error \(error)") }
}
Enter fullscreen mode Exit fullscreen mode

This is the right tool the moment your data has more than one instance of anything — a list of items, notes, sessions, whatever your app's core object is. It's also the right tool if you need the data to survive a reinstall or show up on a second device without the user manually re-entering it.

The decision in one line

If you can describe what you're syncing as "a value," reach for NSUbiquitousKeyValueStore. If you'd describe it as "records" or "a list," reach for CloudKit. Don't let CloudKit's setup overhead push you toward cramming real data into the key-value store — the 1MB ceiling and lack of conflict resolution at the field level will bite you later, usually right when a user has enough data in the app for it to actually matter. Pick based on shape, not based on which one sounds like less work today.

Top comments (0)