Pausing a synced Realm

In migrating to MongoDB Realm from Realm Cloud, I’m attempting to limit syncing for non-paying users if their subscription expires, but they should be able to continue to use their data locally with the same Realm.

I saw in the docs at https://docs.mongodb.com/realm/sdk/react-native/examples/sync-changes-between-devices/#pause-or-resume-a-sync-session that there is the ability to pause syncing, but when I do this, it appears to no longer utilize the Realm that is on the device either. Everything goes dead. It’s as if the database no longer exists.

Is there a way to continue CRUD locally without it syncing changes to the server?

–Kurt

1 Like

Hi @Kurt_Libby1 – I can’t comment on the React-Native. SDK but I did this test on iOS (realm-cocoa):

  • I had some synced data in the app.
  • Paused sync through the Realm UI
  • Added new Objects in the iOS app
  • Restarted the iOS app and confirmed that all of the data was still there
  • Resumed sync from the Realm UI and confirmed that all of the changes made during the sync-pause were synced (and written to Atlas after a short delay for the translator to become active again)

Thanks Andrew.

When you say that you

• Paused the sync through the Realm UI

did you pause sync right after opening the Realm?

For instance, I am attempting to follow the documentation linked in the original post by doing:

let realm;
const config = {
  schema: getSchema(),
  sync: {
    user: app.currentUser,
    partitionValue: `user=${app.currentUser.id}`,
  },
};
try{
  realm = await Realm.open(config);
  const syncSession = realm.syncSession;
  syncSession.pause(); // this is what would be toggled based on subscription status
} catch (error) {
  console.log(error)
}
return realm;

Are you pausing it similarly, right when you open the Realm?

–Kurt

I paused it after the Realm had been opened. I then restarted the app (opening the realm again).

I just retried where I installed the app after sync was paused, and the data still survives an app restart

UPDATE: nevermind. I didn’t realize that when you said the Realm UI that you were talking about the server and not something on the client. I am attempting to pause sync from the client side for an individual device.

–Kurt

Old post:

Ok, well then at least I know it should work.

Now to figure out what’s happening with my code.

Thanks for your help.

Hey @Kurt_Libby1 - I think we might be talking about a couple of different but related concepts here. I believe @Andrew_Morgan has fully paused sync for all users via the Realm App UI, while you’re talking about pausing sync for individual users based on your business logic - in your case, whether or not they have a subscription.

If that’s accurate, I think there’s a different approach you could take. You could use some small function-based checks or something in custom user data to determine whether a user is a subscriber. If the user is not a subscriber, you could open a local realm, rather than opening a synced realm and pausing it immediately. This would enable you to continue doing CRUD locally and not have to worry about pausing and resuming sync (or pausing it indefinitely every time you open a realm).

If you go with this approach, you’d need to write some custom code to handle a case where a user subscribes; where you want to preserve their data from the local realm, and then switch to using a synced realm. Basically, you’d need to copy the data from the local realm and put it into a synced realm when that conversion happens. I don’t have any recommendations for the best way to do that, unfortunately, but I can talk to the team and see if they have any tips.

Hope this gets you moving in the right direction!

2 Likes

Thanks Dachary,

I think you’re right. These are definitely different.

I have the copying from local to synced and back again as a mechanism in my old Realm Cloud code, but I was hoping to not have to do that with MongoDB Realm.

Personal rant: This whole migration thing is hundreds of hours and it doesn’t seem any better than before. It’s a giant headache for nothing. rant over

So then what is the .pause() for? Is there no way for a synced realm to continue to work locally without a connection where I can just turn off the connection? I thought that was one of the main value props of Realm is that it works offline first. Then if they renew their subscription, the syncing is .resume() and everything becomes eventually consistent.

If that’s not the case, I am seriously confused as to why offline/eventually-consistent is even talked about with Realm.

Thanks for any light you can shine on this.

–Kurt

Oof, my sympathies re: the rant! That’s a lot of hours. If there’s something we can do from a documentation or example standpoint to help with that, let me know! I mostly keep an eye on the forums to see where there are places we can improve our documentation, but I’m also happy to take feedback back to the product team. I’m sorry it feels like you haven’t gotten any benefit from migrating. We do have new stuff in the pipeline and are always adding things, so hopefully something in the future will make it all feel worthwhile to you.

Regarding synced realms working locally without a connection - yes, absolutely, sync is designed to handle network connectivity losses gracefully. We offer the .pause() (or .suspend() in some of the other SDKs) method as a convenience method to manage communication between the client and server for a specific realm. It’s intended for temporarily pausing sync within a sync session. But this is for realm files that you want to have syncing to the server regularly; these are realms that need access to the most recent data from the server.

What you’re describing for your app is business logic that dictates whether a user should have a local or a synced realm. In your case, the non-subscribing user’s realm shouldn’t try to communicate with the server at all; they should be using a local-only realm. It never tries to call out to the server; it only does the CRUD locally.

I’m looking at the documentation right now to see where we describe these differences, and it looks like we could definitely improve that. Sorry for any confusion about these concepts! I’ll put in a ticket to work on that.

Regarding copying from the local realm to a synced realm, I spoke with the product team, and there’s not currently an out-of-the-box feature/API for that. But that would definitely make this flow easier to understand and implement. We’ve got a feedback engine, and I’d encourage you to suggest this feature (or anything else you’d like to see!) so our product team knows to prioritize it based on developer requests: https://feedback.mongodb.com/forums/923521-realm/

Oof is right. This extremely disappointing.

I do have about 1500 lines of code that I’ve written that copies a realm to another realm and then reconstructs the relationships, and from what I’ve experienced, it is less than ideal. I was really hopeful that this was not going to be the case going forward.

As @Ian_Ward says, a line of code you don’t have to write is a great line of code.

Instead, I’m going to be adding about 6000 lines of code into four apps to help Realm exist in my app in a usable way.

I don’t drink anymore, but if I did, today would be a good day to pair sadness with scotch.

Please update that .pause() documentation to indicate it’s actual use case and warnings against using it outside of those bounds.

–Kurt

Sorry to be the bearer of bad news, @Kurt_Libby1 ! I’ve made tickets for our documentation team to update language around .pause(), and also more clearly articulate use cases for local vs. synced realms, so hopefully the documentation will better reflect this soon.

I also spoke with @Ian_Ward about this earlier today, and as you mention, he’s a big advocate for making Realm awesome and easy for developers to use. I’m sure he’s seen this thread and will keep your experiences in mind as the product team looks at ways to improve opening realms and copying data between realms.

Meanwhile, if there are other things you spot where the documentation could be better or you’d like to see code examples of how to do something with Realm, feel free to file feedback directly, or keep on posting here. I know a bunch of us keep an eye on the forums for cases like this.

Thanks Dachary.

This just seems like a major oversight.

If the Realm works offline when it is already on the device and the user is cached, the need to copy that entire realm (including all of the possibilities of data loss that comes along with that) seems redundant and ridiculous.

There should be a way to continue using the realm. I understand the need for local realms that are never synced to transition to becoming synced realms. But forcing a synced realm to back into a local realm is a giant lift and feels like I’m still using Realm in its infancy. May as well have just stayed on self hosted.

I migrated to cloud and now to mongodb, and I’m stuck with the same issues (and some new shiny ones as well).

I understand that it is in MongoDB’s interest to never fix this because utilizing synced realms is how you make your money, so I’m not holding my breath on any innovation or effort in this area. In the meantime, I’ll resurrect 4year old code and make it work with this new mess.

Have a great Tuesday! I know I won’t! :man_facepalming:t2:

–Kurt

Hi, @Kurt_Libby1 Have you find any solution? I’m facing the same issue and unable to switch synced realm to back into a local realm and not able to provide local realm service who trying switch Premium plan ( Sync With Cloud ) to Free plan ( Local Realm No sync ).

I have not found a way besides looping through everything to create a new local real and then logging them out of the synced realm.

It has caused problems for me if they don’t finish before the local realm is done being populated, switch to other screens/apps/etc.

Still hoping to figure out how to open the synced Realm and then pause syncing if the subscription is expired, which @Ian_Ward did indicate on a call that it should be possible, but if it is, it is undocumented and I haven’t been able to figure it out. If I do, I’ll post a solution here.

1 Like

The solution you described is what we’d recommend for this use case. Opening two separate realms and iterating through the data while copying the objects between a synced and non-synced realm. Some of the SDKs actually do have API for making a non-sync realm copy of your sync realm - so depending on which direction you are going it could help you - Class: Realm

Not sure why the pause sync API is not working for you but it wasn’tf designed for forever periods of offline, so your mileage may vary there which is why we would recommend using two realms for this use case.

This is so frustrating. During evaluation of Realm as a platform for our subscription based app, we were also led to believe the pause() / resume() methods would accomplish this, as per the documentation. It’s such a common use case.
@Ian_Ward - Can you clarify what the ramifications of using it for longer periods (or indefinitely) offline may be?

1 Like

@_Mark We haven’t tested for this use case because it wasn’t designed for this use case so I can’t really tell you - all I can say is that there are unknowns since it wasn’t designed for this.

That’s why I was asking what goes wrong when you use pause() like this, I’d like to understand what happens.

I’ll test it out again and share my results.

In the meantime, what exactly was pause() designed for?

The documentation is very to the point, but clearly needs explanation:

pause() : Pause a sync session.

1 Like

It was designed for controlling when devices would sync, not that they would never sync, for instance, I imagine if you used this option for a prolonged period of time you could get issues with storage since the sync realm also stores the operations that created the change which can easily be 4x the storage of the actual state - these operations get pruned from he realm after they sync, so imagine if you never sync? Another issue you could run into is there is a server-side feature know as compaction which prunes the operations from the server-side partitions, after a set amount of time it starts pruning old operations if the serverside prunes operations from the partition which is paused then a client could experience a client reset. This will probably not be an issue if the partition you are running is a per-user private realm, more of an issue with shared realms.

Primarily, pause() is to give developers control when the device would sync. For instance, some companies have a requirement to only sync in the evening or at night - or to spread the sync load out across different times the users will sync. It can also be used to conserve battery, etc.

2 Likes

Thanks for the quick response Ian. It appears it was suggested in the feedback engine over a year ago (Disable Sync). I really hope this gets some traction in the near future.

I understand the recommendation is to iterate through two separate realms and update as a subscription is made or expires. This adds risk and complexity, especially as this is performed on a mobile device. Paying for a subscription in a premium app, then waiting … and waiting to be able to continue to use the app is a terrible user experience.

We’re quite stuck now, and will have to re-evaluate our direction forward.

@_Mark , I’m betting/hoping this will get refuted, and I may have mentioned this earlier in the thread, but I’m guessing that this feature will never be added.

Pausing sync is fundamentally against the business model of MongoDB. If the data is staying local on a device and never syncing, they can’t charge us. My guess is that there are a hundred other features that will always bump this to the bottom of any backlog, if it even makes it onto a list.

The frustrating thing for sure is that offline-first is the projected value prop, and for everything that truly is magical about Realm including the syncing stuff that we don’t have to deal with because the technology is so great, handling these migrations from local/synced/back-again is a giant oversight and something that we’ll have to live with if we’re going to keep using Realm.

To be clear, I’m not going anywhere and I love Realm. Realm has helped so much with so many more difficult things by abstracting those things away that this sort of extremely repetitive code to manually copy and recreate connections is just something we’re going to have to live with in the Realm ecosystem.