When I started building Hive Notes, a beekeeping app for iPad and iPhone, one of the first architectural decisions I faced was data persistence. SwiftData or Core Data?
SwiftData is Apple's modern take on local persistence. It has a cleaner syntax, tighter SwiftUI integration, and comes with less boilerplate. Core Data is the two-decade-old workhorse with an Objective-C heritage and a reputation for complexity. On paper, SwiftData seems like the obvious choice for a new project in 2025.
I chose Core Data.
The Complexity of Beekeeping Data
Hive Notes isn't a simple app. The data model of the MVP has 15 Core Data entities: apiaries, hives, queens, and several more. These entities have complex relationships. A queen belongs to a hive, which belongs to an apiary. But queens can also be superseded and tracked historically. Inspections reference hives but also link to photos.
This isn't a to-do list. It's a relational database that needs to handle years of beekeeping records without breaking.
When the data model is this complex, I want full control over how it behaves. I need confidence that edge cases won't silently corrupt the user's data. I need migrations that work reliably when I add features over time.
I didn't feel confident SwiftData could give me that (yet).
What SwiftData Gets Right
I want to be clear: SwiftData isn't a bad framework. It's exciting to see Apple modernizing data persistence for Swift developers.
The syntax is cleaner. Defining a model with the Model macro and property wrappers feels native to Swift in a way that Core Data's NSManagedObject subclasses never did. The boilerplate reduction is real. You no longer need to fiddle with xcdatamodeld files, no more code generation steps, and no more NSManaged properties. Under the hood, SwiftData still relies on Core Data's storage engine, but its abstraction layer behaves differently enough that the underlying stability doesn't automatically transfer to apps built with it.
SwiftUI integration is smoother. Query and the modelContext environment value make fetching and displaying data feel seamless. For straightforward apps, this is a productivity win.
Apple is clearly investing in SwiftData's future. Each WWDC brings improvements, and the framework matures year after year. But maturity is exactly the problem.
SwiftData's Growing Pains
SwiftData was introduced alongside iOS 17 and macOS 14. That's barely two years of real-world usage across the developer community. Compare that to Core Data's two decades.
The issues aren't theoretical. Developers are hitting problems in production.
Unreliable auto-save. SwiftData's automatic saving can fail silently in certain situations. While manually triggering saves reduces the risk, the save lifecycle is still less explicit and less transparent than Core Data's. For an app like Hive Notes, where users record years of beekeeping data, silent save failures are unacceptable.
Relationship inconsistencies. Bidirectional relationships behave unpredictably. You can't use let for bidirectional relationships, and initializations might not trigger correct internal updates. This can cause inconsistencies or crashes. Exactly the kind of edge cases that surface after you've shipped and users have real data.
Array ordering issues. Collections of Model objects can reorder unexpectedly when loaded because SwiftData collections don't support sort descriptors in the same way Core Data fetch requests do. If your app relies on stable ordering, such as the chronological sequence of inspections, this becomes a serious problem.
Performance with large datasets. SwiftData can struggle with large object graphs because it loads data eagerly rather than faulting objects the way Core Data does. A beekeeper with multiple apiaries and years of records can easily accumulate thousands of objects, and user interface performance can degrade noticeably under that load.
Limited migration support. SwiftData currently supports only lightweight migrations. If you need fine-grained control over how data transforms between schema versions, you are blocked. Core Data's support for heavyweight migrations exists because real-world apps eventually require them.
Incomplete batch operations. Batch inserts, deletes, and updates, essential for efficiency in data-heavy apps, aren't fully supported yet.
These aren't obscure edge cases. They're fundamental operations that a complex app needs to handle reliably.
None of these limitations are surprising for a young framework, but they matter when building an app that must remain reliable for years and across many schema evolutions.
The Value of Experience
I've been working with Core Data for over 15 years. I know its quirks. I know where the sharp edges are and how to avoid them. I've built patterns that work, and I've written extensively about the framework on Cocoacasts. That experience is worth something.
When I hit a problem in Core Data, I usually know why it happened and how to fix it. When developers run into problems with SwiftData, they're often the first to encounter that specific issue. The community knowledge base is still thin. Stack Overflow answers are sparse and AI isn't always a great help because it has limited knowledge about it, let alone its latest changes. Debugging can mean reading framework disassembly, filing radars, and waiting.
For a project with a hard deadline, that uncertainty is a risk I didn't want to take.
The Decision Framework
Here's how I thought about the choice:
Choose SwiftData if:
- Your data model is relatively simple
- You're targeting iOS 17+ only
- You value developer experience and clean syntax
- You can tolerate some instability as the framework matures
- Your app isn't storing critical, irreplaceable user data
Choose Core Data if:
- Your data model is complex with many relationships
- You need full control over migrations
- Data reliability is paramount
- You need to support older iOS versions
- You have existing Core Data experience to leverage
- You need advanced querying or batch operations
Hive Notes checked almost every box in favor of Core Data.
No Regrets
I haven't regretted the decision. In fact, I've used Core Data for dozens of projects, and never regretted my decision. While Core Data has its quirks, I love working with it.
Core Data's verbosity is real, and its Objective-C heritage shows, but it works. My 15-entity model persists reliably. iCloud sync functions correctly. Migrations happen without drama. I sleep well knowing that a beekeeper's years of hive records won't vanish because of a framework quirk.
SwiftData will get there. Give it another two or three years of maturation, and it'll likely be the default choice for new projects. Apple is clearly committed to it.
But for Hive Notes, right now, Core Data was the right call. Sometimes boring technology is exactly what you need.
Other Options
I briefly considered SQLite after seeing the excellent series on Point-Free by Brandon and Stephen. It was tempting, but I stuck to my decision and went for boring but proven.
Hive Notes is a beekeeping app designed to help beekeepers spend less time on paperwork and more time with their bees. Learn more at hivenotes.app.