Does Realm Fit My Use Case?

Hi there, I’ve been through the docs a number of times now but I just can’t figure out the answer to my question. Realm seems all or nothing in one direction, which would make it not usable for my project, but maybe people can shed light on what I found to not be documented well. My use case:

  1. Users can download my app on their mobile device and use it offline without issue (this is obviously possible)
  2. Users can pay to upgrade the app to enable syncing via a subscription and link it to a login (this I don’t know? I see you can transition the whole app, but not on a per user instance so far)
  3. If a user wants to stop paying the subscription I’d like to transition them back to just local persistence rather than completely lock them out.

Like I said above, it seems clear that you can take an app that was initially offline only and make it cloud sync only, but I can’t find anything about turning that on and off as needed, or rather even any documentation on the transferring of offline to cloud sync at all. I only see it talked about here on the forums.

I can only assume no one knows the answer to this, or its not possible at this point. So does anyone know if you can turn sync on and off programatically as needed?

@Steven_Lambe There is a connection -suspend and connection -resume API which will allows you to programmatically control the syncing. However, I’m not sure that’s what you are looking for.

Non-sync realms and Sync realms have different file formats and are opened with different configuration parameters. There is no API to convert between the two so you’ll to copy data from one file to another realm file manually.

I’m essentially trying to not force users to signup for basic use, but if they want to pay a subscription fee, then they sign up and can start to sync. Until then though, I want them to have full local abilities without blockers. General flow:

  1. User downloads app
  2. User has most abilities, but local only
  3. User decides they want to subscribe to and as such creates an account
  4. User has multi-platform access and new features
  5. User decides they don’t use extra features enough and decides to cancel subscription and reverts back to the original abilities without syncing turned on, but still has all their data.

A suspend and resume API might work, but I presume that requires an account from the get go which I’m trying to avoid? I’m trying to put up as few barriers to entry as possible. Talking to many in my target audience they are still people who if they are prompted to create an account on first open to use the app essentially offline, they bounce.

Hmm - one thing you might consider is anonymous authentication -
https://docs.mongodb.com/realm/ios/authenticate#anonymous-authentication

That way you can log them in from the start in the code without the user being aware

It likely wouldn’t with the clause of: “An Anonymous user object is not intended to be reused, and once a user logs out, they will not be able to retrieve any previous user data.”

I want to give users the ability to essentially use the app offline indefinitely if the so choose, and optionally turn on syncing, and at that create an account. If the user’s phone, or their identity provider, logged them out for some reason, all their data would essentially be lost. That’s why I’d like to keep it all local until they choose to turn on syncing.

Essentially what I’m getting is it is all or nothing when it comes to syncing. You’re either an offline DB, or an online DB that requires authentication of the user, making it not viable for my usage.

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

  1. Login to their online account

your_app.login(credentials: creds) { result in }

  1. Open a connection to sync’d data

Realm.asyncOpen(configuration: config) { result in }

  1. 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

  1. Get a local realm

let myLocalRealm = try! Realm()

  1. 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.

2 Likes

That sounds a lot more like what I expected to be able to do. To clarify a few of things though:

  1. If I start with offline only DBs, and transition to a synced DB does the underlying database file remain, or does the synced database file have the same name therefore overwriting it?
  2. I’m honestly still not clear how the transition from offline to online works. Are you referencing using the standalone RealmDB, and then transition to the Sync RealmDB and vice versa? Are they separate libraries? Do you have to essentially do the inverse of your online to offline example or does it just read the existing data and go from there?
  3. When transitioning to “synced mode” is there
  1. @Ian_Ward initially recommended using Anon Auth to start users off, but you said the above. That makes more sense to me and is exactly what I want. From your example of how to transition back to offline only I have a good idea of how to do that now, but I am curious if there are any foreseen issues if a user then returns to “sync mode”?

I would be working in React Native, and I kind of get the top half, but I more understand the last code example.

Any help clarifying the above would be appreciated. I found your initial code examples lacking context (I haven’t gone deep with Swift, but I think it’s more just me wondering what my_app was supposed to be and the like). If you are able to example in JS great, otherwise Swift is great as well and maybe just a bit more of a verbose example like your online to offline one might help me understand what you mean?

No - it is not overwritten. When you transition from a local database to sync’d the filename will be different. The local database can be called anything you want but by default it’s called default.realm. Whereas sync’d realms are auto-named according to their partition key; so for example an Object whose partition key is Task Tracker will have a local file name of %22Task%20Tracker%22. Additionally the path to the file stored on the device will be different.

You are in control of that process. If you read in realm results from the local realm, connect to the sync’d realm and write the objects, the files and structure is taken care of for you - the local sync files are created and the objects are written to the server. So yes, if you follow that pattern, it’s the inverse of going from sync to local. It’s really not a big deal - I updated an app we use internally based on the Task Tracker demo to be either online or offline and it took about 30 minutes, including updating the UI.

If you are starting uses off storing the data locally, there is no authentication at all so you do not need Anonymous Users in any way.

Nope. Whether local or online how your code interacts with Realm objects are the same. The difference is how to ‘open a connection’ to realm as it’s different between a local file connection and a sync connection. The documentation has all of that laid out.

lol. Well, the context was in the steps, not the code! The code wasn’t really the important part as steps are identical across the board which was really the point of that. The code itself is swift but if you review the documentation, you will find the corresponding steps and code in React.

Any further examples would just be a duplicate of he existing documentation so I think that’s a great place to start. The Realm Getting Started Guide is available. Once you have a basic app framework coded and feel more comfortable then you can implement sync’ing and the BETA documentation is a great place to start. Sync Data

No code examples required, I think you clarified what I was missing in this reply well. I was missing what the process was when you were talking about transitioning to online mode and I wasn’t sure if it was supposed to be “magic” somehow or if it was a more programatic move. I much prefer a more programatic move so there is more control as it seems there is.

Thank you.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.