SwiftData, Core Data, or GRDB: Choose by the Queries You Actually Run
Choose between SwiftData, Core Data, and GRDB by the operations your data must support, and decide the CloudKit constraints before the first release.
Choosing a persistence framework for an iOS application is not simply a matter of syntax. The crucial factor is the set of queries the app must support and whether it will need to sync data with a server later. This second article in a pair builds on the first by examining three popular frameworks - SwiftData, Core Data, and GRDB - by evaluating how well they can handle typical queries and support offline operation.
The first article sorted the app's data into logical categories like preferences, secrets, domain entities and synchronization metadata. For a travel planning app called TripBoard, five of these six categories had database-free alternatives, leaving only the domain entities like trips, places and bookings that require persistence. Those are the domain entities the article focuses on.
Four key questions then decide the choice of framework. First, what are the most common queries and the most expensive one? Second, how many rows might the largest table hold after three years of data accumulation? Third, does it have to run fully offline, with devices staying in sync? Fourth, how will the schema evolve after the first release and how to test an upgrade from an older version?
SwiftData could be a good fit for a new SwiftUI app targeting modern iOS versions, especially when the model has a simple relationship structure and doesn't rely heavily on aggregates, full-text or bulk operations. It handles fetching and relationship sorting with its @Query annotations and is convenient for SwiftUI projects. However, SwiftData struggles with bulk updates and aggregate queries, requiring fetching objects one by one to perform tasks like marking records as synchronized.
It also lacks support for unique constraints and nonoptional relationships required for CloudKit synchronization.
Core Data is a more traditional ORM with mature features, but it adds complexity in terms of management, especially when transitioning to cloud sync. Its core entities are modeled as NSManagedObjects with relationships, relationships and fetch requests. The fetching and relationships fit operations one and two, but operations involving bulk updates and aggregates are more cumbersome. Core Data also lacks direct support for CloudKit schema constraints.
GRDB is a lightweight SQLite wrapper that provides a simpler API while still supporting core relational operations. It handles basic fetching and relationships well, but more complex aggregate queries require additional Swift code. Its simplicity and direct mapping to SQL make it a good choice for more technical projects that want fine-grained control over the database. Like SwiftData, GRDB does not natively support CloudKit constraints.
In summary, the choice depends on the specific query patterns and offline requirements of your app. SwiftData offers the simplest API for SwiftUI projects with modest relationship graphs but lacks bulk processing capabilities. Core Data provides a mature ORM with good relationship handling but adds complexity for schema and sync management.
GRDB offers a lightweight option for projects that need a simple SQLite wrapper and can handle aggregates through additional Swift code. Consider the actual query workload, potential data growth, offline requirements, and framework complexity before making a decision.
Written by urgent.news from HackerNoon's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.