SwiftData sync without iCloud
Sync a SwiftData store across a person's devices with your own sign-in instead of CloudKit, and what you give up and gain by doing it.
SwiftData can sync through CloudKit with a single setting, and for many apps that is the right choice: it costs nothing and needs no server. It stops fitting when you need one of the things it cannot do.
When CloudKit stops fitting
- The person must be signed in to iCloud, with room left in their iCloud storage. Without it, nothing syncs and your app is not told much.
- Your model has to fit CloudKit: every property optional or with a default, no unique attributes, and every relationship optional.
- Only Apple devices. There is no CloudKit for Android.
- You cannot see your people's data. It is in each person's private iCloud database, so you cannot export it, answer an access request from your side, or delete an account's data on the server.
- Sync happens when the system decides, and you cannot tell when it is done.
Syncing SwiftData with SyncPilled
Keep a plain local SwiftData store (no cloudKitDatabase), and let SyncPilled
copy it between the person's devices, signed in with your app's own provider.
- Give each synced model a stable id and an
updatedAtdate. - Write a data source: a snapshot of every synced record as JSON,
and an
applythat writes in what arrives, checking each record is unchanged in the same step. - Call
engine.sync()at launch, on returning to the foreground, and after saving.
Your model needs nothing CloudKit asks for: unique attributes and required properties are fine, because SyncPilled sees JSON, not your schema.
What you take on
You run, or rent, a server: the hosted version, or your own Cloudflare account. Sign-in is yours: Firebase, Supabase, Auth0, Clerk or Sign in with Apple. And conflicts are settled per record, by the latest edit, rather than by CloudKit's own rules.