CloudKit Sync Stalls During Initial Large Data Hydration on New Device (SwiftData Local-First Architecture)

Hi everyone,

I’m facing an issue with CloudKit sync getting stuck during initial device migration in my SwiftData-based app.

The app follows a local-first architecture using SwiftData + CloudKit sync, and works correctly for:

✔ Incremental sync ✔ Bi-directional updates ✔ Small datasets

However, when onboarding a new device with large historical data, sync becomes extremely slow or appears stuck. Even after two hours data is not fully synced. ~6900 Transactions

🚨 Problem

When installing the app on a new iPhone and enabling iCloud sync: • Initial hydration starts • A small amount of data syncs • Then sync stalls indefinitely

Observed behaviour: • iPhone → Mac sync works (new changes sync back) • Mac → iPhone large historical migration gets stuck • Reinstalling app / clearing container does not resolve issue • Sync never completes full migration

This gives the impression that:

CloudKit is trickling data but not progressing after a certain threshold.

The architecture is: • SwiftData local store • Manual CloudKit sync layer • Local-first persistence • Background push/pull sync

So I understand:

✔ Conflict resolution is custom ✔ Initial import may not be optimized by default

But I expected CloudKit to eventually deliver all records.

Instead, the new device remains permanently in a “partial state”.

🔍 Observations • No fatal CloudKit errors • No rate-limit errors • No quota issues • iCloud is available • Sync state remains “Ready” • Hydration remains “mostlyReady”

Meaning:

CloudKit does not report failure — but data transfer halts.

🤔 Questions

Would appreciate guidance on:

  1. Is CloudKit designed to support large initial dataset migration via manual sync layers?

Or is this a known limitation vs NSPersistentCloudKitContainer?

  1. Does CloudKit internally throttle historical record fetches?

Could it silently stall without error when record volume is high?

  1. Is there any recommended strategy for: • Bulk initial migration • Progressive hydration • Forcing forward sync progress

  1. Should initial migration be handled outside CloudKit (e.g. via file transfer / backup restore) before enabling sync?

🎯 Goal

I want to support: • Large historical onboarding • Multi-device sync • User-visible progress

Without forcing migration to Core Data.

🙏 Any advice on: • Best practices • Debugging approach • CloudKit behavior in such scenarios

would be greatly appreciated.

Thank you!

CloudKit Sync Stalls During Initial Large Data Hydration on New Device (SwiftData Local-First Architecture)
 
 
Q