I really think Realm fits this use case pretty easily.
Let me clarify a couple of things:
If the user’s phone, or their identity provider, logged them out for some reason, all their data would essentially be lost
Realm is an offline first database - meaning that data is always stored locally first and then sync’d to the cloud. If the user disconnects from their account, their data is still on the device and not lost.
You’re either an offline DB, or an online DB that requires authentication of the user,
Right! According to how the use case was described above, that’s exactly this use case; When they want to use sync’d data, they have an account and when they are local only, they don’t. Sound like a good fit!
For your use case, if the users starts off local-only, they don’t need any kind of account. When they choose to move to sync, they would create an account and their data would sync.
If later they decide they no longer want sync’d data, it would not be difficult to move back to local only storage not requiring an account, and you could remove the online data.
Let me speak to this with some Code (Swift in this case) as talking to sync’d data vs local data is just a few different lines of code:
Reading sync’d data is pretty much three steps
- Login to their online account
your_app.login(credentials: creds) { result in }
- Open a connection to sync’d data
Realm.asyncOpen(configuration: config) { result in }
- Read sync’d data, keeping in mind this is actually read from a local file which is sync’d to the server
let realm = try! Realm(configuration: user!.configuration(partitionValue: somePartition))
let mySyncdTasks = realm.objects(TaskClass.self) //read the sync’d tasks
Reading local data it’s pretty much two steps
- Get a local realm
let myLocalRealm = try! Realm()
- read data
let myTasks = realm.objects(TaskClass.self)
when the user switches from sync to local, all of the data is already stored locally so copying it from the local sync Realm file to a local only file would be pretty painless - the internal file formats are slightly different as @Ian_Ward mentioned above so that step is required.
The code to move sync’d data to local data is just this:
let taskResults = syncdRealm.objects(TaskClass.self) //this reads all sync'd tasks
let realm = try! Realm() //this will create a local default.realm file
try! realm.write {
for task in taskResults {
let localTask = realm.create(TaskClass.self, value: task, update: .all) //write out the data
realm.add(localTask)
}
}
I would encourage you to write some code to get the feel for Realm and explore it for this use case.
If there’s something we didn’t address, please let us know as it really does seem like a good fit to me.