axiom-sqlitedata-migration
Use when migrating from SwiftData to SQLiteData — decision guide, pattern equivalents, code examples, CloudKit sharing (SwiftData can't), performance benchmarks, gradual migration strategy
Best use case
axiom-sqlitedata-migration is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when migrating from SwiftData to SQLiteData — decision guide, pattern equivalents, code examples, CloudKit sharing (SwiftData can't), performance benchmarks, gradual migration strategy
Teams using axiom-sqlitedata-migration should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/axiom-sqlitedata-migration/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How axiom-sqlitedata-migration Compares
| Feature / Agent | axiom-sqlitedata-migration | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when migrating from SwiftData to SQLiteData — decision guide, pattern equivalents, code examples, CloudKit sharing (SwiftData can't), performance benchmarks, gradual migration strategy
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Migrating from SwiftData to SQLiteData
## When to Switch
```
┌─────────────────────────────────────────────────────────┐
│ Should I switch from SwiftData to SQLiteData? │
├─────────────────────────────────────────────────────────┤
│ │
│ Performance problems with 10k+ records? │
│ YES → SQLiteData (10-50x faster for large datasets) │
│ │
│ Need CloudKit record SHARING (not just sync)? │
│ YES → SQLiteData (SwiftData cannot share records) │
│ │
│ Complex queries across multiple tables? │
│ YES → SQLiteData + raw GRDB when needed │
│ │
│ Need Sendable models for Swift 6 concurrency? │
│ YES → SQLiteData (value types, not classes) │
│ │
│ Testing @Model classes is painful? │
│ YES → SQLiteData (pure structs, easy to mock) │
│ │
│ Happy with SwiftData for simple CRUD? │
│ YES → Stay with SwiftData (simpler for basic apps) │
│ │
└─────────────────────────────────────────────────────────┘
```
---
## Pattern Equivalents
| SwiftData | SQLiteData |
|-----------|------------|
| `@Model class Item` | `@Table nonisolated struct Item` |
| `@Attribute(.unique)` | `@Column(primaryKey: true)` or SQL UNIQUE |
| `@Relationship var tags: [Tag]` | `var tagIDs: [Tag.ID]` + join query |
| `@Query var items: [Item]` | `@FetchAll var items: [Item]` |
| `@Query(sort: \.title)` | `@FetchAll(Item.order(by: \.title))` |
| `@Query(filter: #Predicate { $0.isActive })` | `@FetchAll(Item.where(\.isActive))` |
| `@Environment(\.modelContext)` | `@Dependency(\.defaultDatabase)` |
| `context.insert(item)` | `Item.insert { Item.Draft(...) }.execute(db)` |
| `context.delete(item)` | `Item.find(id).delete().execute(db)` |
| `try context.save()` | Automatic in `database.write { }` block |
| `ModelContainer(for:)` | `prepareDependencies { $0.defaultDatabase = }` |
---
## Code Example
**SwiftData (Before)**
```swift
import SwiftData
@Model
class Task {
var id: UUID
var title: String
var isCompleted: Bool
var project: Project?
init(title: String) {
self.id = UUID()
self.title = title
self.isCompleted = false
}
}
struct TaskListView: View {
@Environment(\.modelContext) private var context
@Query(sort: \.title) private var tasks: [Task]
var body: some View {
List(tasks) { task in
Text(task.title)
}
}
func addTask(_ title: String) {
let task = Task(title: title)
context.insert(task)
}
func deleteTask(_ task: Task) {
context.delete(task)
}
}
```
**SQLiteData (After)**
```swift
import SQLiteData
@Table
nonisolated struct Task: Identifiable {
let id: UUID
var title = ""
var isCompleted = false
var projectID: Project.ID?
}
struct TaskListView: View {
@Dependency(\.defaultDatabase) var database
@FetchAll(Task.order(by: \.title)) var tasks
var body: some View {
List(tasks) { task in
Text(task.title)
}
}
func addTask(_ title: String) {
try database.write { db in
try Task.insert {
Task.Draft(title: title)
}
.execute(db)
}
}
func deleteTask(_ task: Task) {
try database.write { db in
try Task.find(task.id).delete().execute(db)
}
}
}
```
**Key differences:**
- `class` → `struct` with `nonisolated`
- `@Model` → `@Table`
- `@Query` → `@FetchAll`
- `@Environment(\.modelContext)` → `@Dependency(\.defaultDatabase)`
- Implicit save → Explicit `database.write { }` block
- Direct init → `.Draft` type for inserts
- `@Relationship` → Explicit foreign key + join
---
## CloudKit Sharing (SwiftData Can't Do This)
SwiftData supports CloudKit **sync** but NOT **sharing**. SQLiteData is the only Apple-native option for record sharing.
```swift
// 1. Setup SyncEngine with sharing
prepareDependencies {
$0.defaultDatabase = try! appDatabase()
$0.defaultSyncEngine = try SyncEngine(
for: $0.defaultDatabase,
tables: Task.self, Project.self
)
}
// 2. Share a record
@Dependency(\.defaultSyncEngine) var syncEngine
@State var sharedRecord: SharedRecord?
func shareProject(_ project: Project) async throws {
sharedRecord = try await syncEngine.share(record: project) { share in
share[CKShare.SystemFieldKey.title] = "Join my project!"
}
}
// 3. Present native sharing UI
.sheet(item: $sharedRecord) { record in
CloudSharingView(sharedRecord: record)
}
```
**Sharing enables:** Collaborative lists, shared workspaces, family sharing, team features.
---
## Performance Comparison
| Operation | SwiftData | SQLiteData | Improvement |
|-----------|-----------|------------|-------------|
| Insert 50k records | ~4 minutes | ~45 seconds | **5x** |
| Query 10k with predicate | ~2 seconds | ~50ms | **40x** |
| Memory (10k objects) | ~80MB | ~20MB | **4x smaller** |
| Cold launch (large DB) | ~3 seconds | ~200ms | **15x** |
*Benchmarks approximate, vary by device and data shape.*
---
## Migrating Existing User Data
**Critical**: Schema migration alone loses all user data. You must export from SwiftData and import into SQLiteData.
```swift
// 1. Read all records from SwiftData's backing store
func migrateExistingData(from modelContext: ModelContext, to database: any DatabaseWriter) throws {
// Fetch all SwiftData records
let descriptor = FetchDescriptor<SwiftDataTask>()
let existingTasks = try modelContext.fetch(descriptor)
// 2. Bulk insert into SQLiteData
try database.write { db in
for task in existingTasks {
try SQLiteTask.insert {
SQLiteTask.Draft(
id: task.id,
title: task.title,
isCompleted: task.isCompleted,
projectID: task.project?.id
)
}
.execute(db)
}
}
// 3. Verify migration
let count = try database.read { db in
try SQLiteTask.fetchCount(db)
}
assert(count == existingTasks.count, "Migration count mismatch!")
}
```
**Migration checklist:**
- [ ] Export all models before deleting SwiftData container
- [ ] Migrate relationships (fetch parent IDs for foreign keys)
- [ ] Verify record counts match after migration
- [ ] Keep SwiftData container as backup until confirmed working
- [ ] Run migration on first launch with a version flag in UserDefaults
## Gradual Migration Strategy
You don't have to migrate everything at once:
1. **Add SQLiteData for new features** — Keep SwiftData for existing simple CRUD
2. **Migrate one model at a time** — Start with the performance bottleneck
3. **Use separate databases initially** — SQLiteData for heavy data/sharing, SwiftData for preferences
4. **Consolidate if needed** — Or keep hybrid if it works
---
## Common Gotchas
### Relationships → Foreign Keys
```swift
// SwiftData: implicit relationship
@Relationship var tasks: [Task]
// SQLiteData: explicit column + query
// In child: var projectID: Project.ID
// To fetch: Task.where { $0.projectID.eq(#bind(project.id)) }
```
### Cascade Deletes
```swift
// SwiftData: @Relationship(deleteRule: .cascade)
// SQLiteData: Define in SQL schema
// "REFERENCES parent(id) ON DELETE CASCADE"
```
### No Automatic Inverse
```swift
// SwiftData: @Relationship(inverse: \Task.project)
// SQLiteData: Query both directions manually
let tasks = Task.where { $0.projectID.eq(#bind(project.id)) }
let project = Project.find(task.projectID)
```
---
**Related Skills:**
- `axiom-sqlitedata` — Full SQLiteData API reference
- `axiom-swiftdata` — SwiftData patterns if staying with Apple's framework
- `axiom-grdb` — Raw GRDB for complex queries
---
**History:** See git log for changesRelated Skills
sql-migration-generator
Sql Migration Generator - Auto-activating skill for Backend Development. Triggers on: sql migration generator, sql migration generator Part of the Backend Development skill category.
managing-database-migrations
Process use when you need to work with database migrations. This skill provides schema migration management with comprehensive guidance and automation. Trigger with phrases like "create migration", "run migrations", or "manage schema versions".
exa-upgrade-migration
Upgrade exa-js SDK versions and handle breaking changes safely. Use when upgrading the Exa SDK, detecting deprecations, or migrating between exa-js versions. Trigger with phrases like "upgrade exa", "exa update", "exa breaking changes", "update exa-js", "exa new version".
exa-migration-deep-dive
Migrate from other search APIs (Google, Bing, Tavily, Serper) to Exa neural search. Use when switching to Exa from another search provider, migrating search pipelines, or evaluating Exa as a replacement for traditional search APIs. Trigger with phrases like "migrate to exa", "switch to exa", "replace google search with exa", "exa vs tavily", "exa migration", "move to exa".
evernote-upgrade-migration
Upgrade Evernote SDK versions and migrate between API versions. Use when upgrading SDK, handling breaking changes, or migrating to newer API patterns. Trigger with phrases like "upgrade evernote sdk", "evernote migration", "update evernote", "evernote breaking changes".
evernote-migration-deep-dive
Deep dive into Evernote data migration strategies. Use when migrating to/from Evernote, bulk data transfers, or complex migration scenarios. Trigger with phrases like "migrate to evernote", "migrate from evernote", "evernote data transfer", "bulk evernote migration".
elevenlabs-upgrade-migration
Upgrade ElevenLabs SDK versions and migrate between API model generations. Use when upgrading the elevenlabs-js or elevenlabs Python SDK, migrating from v1 to v2 models, or handling deprecations. Trigger: "upgrade elevenlabs", "elevenlabs migration", "elevenlabs breaking changes", "update elevenlabs SDK", "migrate elevenlabs model", "eleven_v3 migration".
documenso-upgrade-migration
Manage Documenso API version upgrades and SDK migrations. Use when upgrading from v1 to v2 API, updating SDK versions, or migrating between Documenso versions. Trigger with phrases like "documenso upgrade", "documenso v2 migration", "update documenso SDK", "documenso API version".
documenso-migration-deep-dive
Execute comprehensive Documenso migration strategies for platform switches. Use when migrating from other signing platforms, re-platforming to Documenso, or performing major infrastructure changes. Trigger with phrases like "migrate to documenso", "documenso migration", "switch to documenso", "documenso replatform", "replace docusign".
deepgram-upgrade-migration
Plan and execute Deepgram SDK upgrades and model migrations. Use when upgrading SDK versions (v3->v4->v5), migrating models (Nova-2 to Nova-3), or planning API version transitions. Trigger: "upgrade deepgram", "deepgram migration", "update deepgram SDK", "deepgram version upgrade", "nova-3 migration".
deepgram-migration-deep-dive
Deep dive into migrating to Deepgram from other transcription providers. Use when migrating from AWS Transcribe, Google Cloud STT, Azure Speech, OpenAI Whisper, AssemblyAI, or Rev.ai to Deepgram. Trigger: "deepgram migration", "switch to deepgram", "migrate transcription", "deepgram from AWS", "deepgram from Google", "replace whisper with deepgram".
databricks-upgrade-migration
Upgrade Databricks runtime versions and migrate between features. Use when upgrading DBR versions, migrating to Unity Catalog, or updating deprecated APIs and features. Trigger with phrases like "databricks upgrade", "DBR upgrade", "databricks migration", "unity catalog migration", "hive to unity".