Lightweight Migrations and CloudKit Sync
Migrating schema changes and enabling CloudKit sync with NSPersistentCloudKitContainer.
Lightweight Migrations and CloudKit Sync is a free Swift Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Migrations?
When you change your Core Data or SwiftData model (add/rename/remove attributes), you must migrate existing stores.
// Without migration, app crashes on launch:
// "The model used to open the store is incompatible with the one used to create the store"Lightweight Migration in Core Data
Core Data can automatically infer simple migrations (add attribute, rename, remove) without a mapping model.
let desc = NSPersistentStoreDescription(url: storeURL)
desc.shouldMigrateStoreAutomatically = true
desc.shouldInferMappingModelAutomatically = true
container.persistentStoreDescriptions = [desc]Version History in .xcdatamodeld
Create a new model version in Xcode: Editor → Add Model Version. Set the current version to the new one.
// In MyModel.xcdatamodeld:
// ├── MyModel.xcdatamodel (v1 - old)
// └── MyModel 2.xcdatamodel (v2 - current)
// Set current version to v2 in File InspectorSwiftData Schema Versioning
Use VersionedSchema and SchemaMigrationPlan to manage SwiftData model versions.
enum AppSchemaV1: VersionedSchema {
static var versionIdentifier = Schema.Version(1,0,0)
static var models: [any PersistentModel.Type] { [ItemV1.self] }
@Model final class ItemV1 { var name: String; init(name: String) { self.name = name } }
}SchemaMigrationPlan
Define migration stages between versions in a SchemaMigrationPlan to guide SwiftData through upgrades.
enum AppMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] { [AppSchemaV1.self, AppSchemaV2.self] }
static var stages: [MigrationStage] { [migrateV1toV2] }
static let migrateV1toV2 = MigrationStage.lightweight(fromVersion: AppSchemaV1.self, toVersion: AppSchemaV2.self)
}Custom Migration Stage
For complex migrations (data transforms), use a .custom stage with willMigrate and didMigrate closures.
static let migrateV1toV2 = MigrationStage.custom(
fromVersion: AppSchemaV1.self,
toVersion: AppSchemaV2.self,
willMigrate: { context in
// transform old data
},
didMigrate: nil
)NSPersistentCloudKitContainer
Replace NSPersistentContainer with NSPersistentCloudKitContainer to enable CloudKit sync.
let container = NSPersistentCloudKitContainer(name: "MyModel")
container.loadPersistentStores { _, error in
if let error { fatalError("\(error)") }
}
container.viewContext.automaticallyMergesChangesFromParent = trueCloudKit Requirements
CloudKit sync requires: signed-in iCloud account, CloudKit entitlement, and a CloudKit container configured in the developer portal.
// Xcode: Signing & Capabilities → + → iCloud → CloudKit
// Enable "Use CloudKit" in Core Data model inspectorSwiftData with CloudKit
Pass a ModelConfiguration with cloudKitDatabase to enable CloudKit sync in SwiftData.
let config = ModelConfiguration(
schema: schema,
cloudKitDatabase: .automatic
)
let container = try ModelContainer(for: schema, configurations: config)Handling Sync Conflicts
Core Data CloudKit resolves conflicts using a last-write-wins policy. Design models to minimize concurrent write contention.
// Best practice: keep models granular
// One attribute per write concern
// Avoid large blobs that frequently changeTesting Migrations
Test migrations on a copy of the production store before shipping to catch issues before users are affected.
// Copy production store to a temp location
// Load it with the new container and verify objects are intactMigration Monitoring
Listen for Core Data migration notifications to show progress UI during long migrations.
NotificationCenter.default.addObserver(
forName: .NSPersistentStoreCoordinatorStoresWillChange,
object: container.persistentStoreCoordinator,
queue: .main
) { _ in showMigrationProgress() }Quick Check
Which NSPersistentContainer subclass enables automatic CloudKit sync?
Lesson Recap
Enable lightweight migration with shouldMigrateStoreAutomatically for simple changes. Use VersionedSchema + SchemaMigrationPlan for SwiftData. Enable CloudKit sync by swapping to NSPersistentCloudKitContainer or ModelConfiguration(cloudKitDatabase: .automatic).
Frequently asked questions
Is the “Lightweight Migrations and CloudKit Sync” lesson free?
Yes — the full text of “Lightweight Migrations and CloudKit Sync” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.
What will I learn in “Lightweight Migrations and CloudKit Sync”?
Migrating schema changes and enabling CloudKit sync with NSPersistentCloudKitContainer. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Lightweight Migrations and CloudKit Sync” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Core Data Stack: NSPersistentContainer Setup
- SwiftData @Model and ModelContext
- Relationships and Fetch Descriptors
- Lightweight Migrations and CloudKit Sync