BackupKit
Kotlin Multiplatform backup into the user's own cloud: iCloud on iOS, the Google Drive app-data folder on Android. No server, no account on your side.
Why it exists
Every app with a wordbook or a journal eventually needs a new phone not to lose the user's stuff. A backend for that means accounts, hosting, and a privacy policy that says you hold user data. The user already pays for a cloud. BackupKit puts the files there, invisible to them, readable only by your app, with an engine that keeps the mirror correct across kills, retries and account switches.
What it does
- The user's cloud, not yours. An app-private iCloud container, or the hidden appDataFolder in Drive that WhatsApp uses. Nothing reaches a server of yours, because there is not one.
- Zero code on iOS, one tap on Android. The iCloud entitlement is the entire iOS setup. Android shows Google's consent dialog once.
- Complete or absent, never half. The engine diffs, uploads the marker last, saves state after every step, resumes after a kill, and refuses to merge two accounts.
- Restore that survives being killed. A typed probe, a write hold, a resumable download with a commit boundary and per-file attempts.
- Typed errors. Seven CloudError values. Nothing platform-specific leaks into your code.
- Small. About 1,200 lines. No DI framework, no Compose, no Firebase, and on iOS it links no HTTP client at all.
Getting started
backupkit = { module = "com.vocabloot:backupkit", version = "0.2.0" }
commonMain.dependencies {
implementation(libs.backupkit)
}
val engine = SyncEngine(
storage = storage, // CloudKitStorage / ICloudStorage on iOS,
// GoogleDriveStorage(context) on Android
stateStore = FileSyncStateStore("$dir/backupkit-state.json"),
policy = SyncPolicy(markerPath = "backup.json"),
)
// The marker is uploaded last, so its presence is what means "complete".
val outcome = engine.sync(snapshot)
One entitlement on iOS and one OAuth client on Android are the whole platform setup. Both are written out step by step on the documentation site.
Support matrix
| Android | iOS | |
|---|---|---|
| Where the files go | Drive appDataFolder | iCloud container (CloudKit or Drive) |
| Setup you do | One OAuth client | One entitlement |
| User sees a prompt | Once, Google's own dialog | No |
| HTTP client linked | Yes, for the Drive REST API | No |
Kotlin 2.3, Gradle 9.0, AGP 9.0, Android minSdk 24, iOS 16 and Xcode 16 or newer. Versioning and the durability promise are on the stability page.
Who is using it
Vocabloot, which is where it came from. The wordbook it backs up is a filesystem manifest plus sibling image files, and the durability code it grew out of had already been through two rewrites before it became a library.
Everything else
- Source on GitHub issues, discussions and the samples
- Documentation setup, guides, recipes, FAQ and known issues
- API reference generated from the source by Dokka
- Maven Central every published version