GRDB.swift: A SQLite Toolkit for iOS and macOS Application Development
A toolkit for SQLite databases, with a focus on application development
At a glance
- What is it?
- GRDB.swift is a Swift toolkit for SQLite databases, focused on application development rather than research or server-side use. It provides a type-safe query interface, database change observation, schema migrations, and support for concurrent reads and writes, all on top of the SQLite file your app already controls.
- Who is it for?
- GRDB.swift is the right choice for iOS and macOS developers who want full SQLite control, support for iOS 13 and later, and a library that has been maintained continuously since 2015. The query interface handles most operations without raw SQL while keeping SQL access available for complex queries.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Persistent Storage for Apple Platform Applications
GRDB.swift addresses a concrete need in iOS and macOS development: storing application data persistently in SQLite with a library that handles concurrency, schema evolution, and change notifications. The library has been in development since 2015, according to the README tagline, and targets the full range of current Apple platforms: iOS 13.0+, macOS 10.15+, tvOS 13.0+, and watchOS 7.0+.
The README lists four built-in tools that address common needs in application development: SQL generation (so that developers can work with Swift types rather than raw SQL strings), database observation (notifications when stored values change, for driving live UI updates), robust concurrency (support for multi-threaded access, including WAL mode for concurrent reads and writes), and schema migrations (for evolving the database as new app versions are released).
The library's stated position is that it does not hide SQLite. It enhances application code with persistence methods and a query interface, but it also accepts hand-written SQL throughout. The README explicitly says "Come with your SQL and SQLite skills, or learn new ones as you go."
Opening a Connection and Defining the Schema
Every GRDB interaction starts by opening a database connection. The README demonstrates the full setup flow in four steps:
import GRDB
// 1. Open a database connection
let dbQueue = try DatabaseQueue(path: "/path/to/database.sqlite")
// 2. Define the database schema
try dbQueue.write { db in
try db.create(table: "player") { t in
t.primaryKey("id", .text)
t.column("name", .text).notNull()
t.column("score", .integer).notNull()
}
}The `DatabaseQueue` type opens a single serialized connection suitable for most applications. The `write` closure executes in a transaction, and the schema definition uses a builder syntax that generates the CREATE TABLE statement. Column constraints like `.notNull()` are expressed as Swift method calls rather than SQL strings.
For applications that need concurrent reads alongside writes, `DatabasePool` provides WAL mode. The README notes that WAL databases support concurrent reads and writes, and that GRDB handles the thread safety of multi-threaded access.
Record Types and the Swift Query Interface
The central pattern in GRDB is a record type: a Swift struct or class that conforms to `FetchableRecord` and `PersistableRecord`. When a type also conforms to `Codable`, the synthesis of database mapping is automatic:
struct Player: Codable, Identifiable, FetchableRecord, PersistableRecord {
var id: String
var name: String
var score: Int
}With that conformance, GRDB can insert, update, delete, and fetch `Player` values using the Swift query interface:
try dbQueue.read { db in
let player = try Player.find(db, id: "1")
let arthur = try Player.filter { $0.name == "Arthur" }.fetchOne(db)
let bestPlayers = try Player.order(\.score.desc).limit(10).fetchAll(db)
let playerCount = try Player.fetchCount(db)
}The filter and order expressions are type-checked at compile time. Passing an incorrect column name or an incompatible type in a query expression is a compile-time error rather than a runtime crash.
SQL is always accepted alongside the query interface. The README shows that raw SQL queries, SQL interpolation for safe injection prevention, and direct row access are all available when the query interface does not cover the needed operation.
Database Observation for Live UI Updates
GRDB's `ValueObservation` type tracks the result of a database query and delivers updates whenever the underlying data changes. The observation start call accepts error and change handlers:
let observation = ValueObservation.tracking { db in
try Player.fetchAll(db)
}
let cancellable = observation.start(
in: dbQueue,
onError: { error in ... },
onChange: { (players: [Player]) in print("Fresh players: \(players)") })For applications using Swift concurrency, the same observation can be consumed as an `AsyncSequence`:
for try await players in observation.values(in: dbQueue) {
print("Fresh players: \(players)")
}The README also shows publishers for Combine integration and an observable sequence for RxSwift. This means that a SwiftUI view, a UIKit view controller using Combine, or a reactive pipeline using RxSwift can all consume database updates with the same underlying observation mechanism.
The practical consequence for application developers is that a list of records displayed in a view stays current automatically when another part of the app (or a background sync task) modifies the database, without manual cache invalidation or polling.
What GRDB Asks More of the Developer
GRDB requires Xcode 16.3 and Swift 6.1 for the current v7.x series. The README states this as a hard requirement. Applications targeting older toolchains or Swift versions need to use an earlier GRDB release, and the CHANGELOG contains the version compatibility history.
Schema migrations in GRDB are written in code, not auto-generated. Each migration is a numbered closure that executes SQL or uses the table builder. There is no inspection of the current schema to generate migration code automatically. This means that as the data model evolves across app versions, each schema change must be written as an explicit migration step and tested against the previous schema.
GRDB is SQLite-only. It does not provide an abstraction layer that could swap to a server-side database. For applications that begin locally and later require server-side storage or sync, the database layer would need to be replaced or duplicated. The library's documentation (in the Documentation/ folder) covers syncing patterns, but only for SQLite to SQLite synchronization.
SwiftData as the Alternative and Maintenance
SwiftData is Apple's own persistence framework, introduced for iOS 17, macOS 14, and later. It uses Swift macros to infer a data model from type annotations and integrates directly with SwiftUI. SwiftData abstracts away the underlying storage entirely, which means developers do not write SQL or manage a SQLite file directly.
The difference with GRDB is in platform coverage and control. GRDB supports iOS 13+, macOS 10.15+, and earlier Apple platform versions that predate SwiftData. GRDB also exposes the full SQLite surface through SQL access alongside the query interface, which is useful for complex queries or for teams with existing SQLite knowledge. SwiftData hides the storage implementation and does not provide SQL access.
For new projects targeting iOS 17+ and macOS 14+, SwiftData offers tighter integration with Apple's ecosystem. For projects that must support earlier iOS versions, that need direct SQL access, or that have existing SQLite files they want to manage with full control, GRDB remains a capable choice.
GRDB.swift is released under the MIT license. The last push to the repository was on September 27, 2026, and the latest release is v7.11.1, published June 18, 2026. The README notes that the library has been serving the community since 2015.
Editorial conclusion
GRDB.swift is the right choice for iOS and macOS developers who want full SQLite control, support for iOS 13 and later, and a library that has been maintained continuously since 2015. The query interface handles most operations without raw SQL while keeping SQL access available for complex queries. The library requires Swift 6.1 and Xcode 16.3 for the current v7.x release; teams on older toolchains should check the CHANGELOG for the last compatible version before upgrading. The detailed documentation in Documentation/ and the GitHub discussions are the first places to look when evaluating edge cases in migrations or concurrency.
Frequently asked questions
What is GRDB.swift?
GRDB.swift is a Swift toolkit for SQLite databases focused on iOS and macOS application development. It provides a type-safe query interface, database change observation for driving live UI updates, schema migrations, and WAL concurrency support.
How do you install GRDB.swift with Swift Package Manager?
GRDB.swift is distributed as a Swift package. Add the package to your Xcode project via File > Add Package Dependencies and enter the GitHub URL. The Package.swift file at the repository root defines the package targets and Swift 6.1 requirement.
How does GRDB.swift handle concurrent database access?
GRDB provides DatabasePool for WAL mode databases, which supports concurrent reads alongside writes. DatabaseQueue provides a single serialized connection for simpler access patterns. Both types handle multi-threaded access safely.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/groue-grdb-swift)