What's the best way to use Realm Sync data on a website?

I want to create a webapp using the same data that’s being used by my apps (Realm SDK, .NET), what’s the best way to go? Just upload the .realm file to the web hosting or should I be considering direct connection to Atlas, if so, what’s the best practice?

It depends on whether you want server side rendering or not. If you do, then you can sync the Realm file on the server and use it as a sort of a local cache to return data from. Alternatively, you can also use the GraphQL API to fetch data directly from the client.

1 Like

Yes but how each scenarios will affect performance, also, if I decide to encrypt the realm database, I think there is a limitation on concurrent opening of encrypted file, which potentially can result in an error, so I’m looking for the best practice in such situation.

And yes, the rendering is going to be on server.

The limitation on concurrent access of encrypted/synchronized Realms concerns accessing them from different processes. If your webserver runs a single process, which is what you typically do with .NET, you should be fine.

Adding encryption to the database is likely to impact performance by 5-10%.

One thing to keep in mind when it comes to ASP.NET Core is that you don’t get a synchronization context installed on the thread handling the request pipeline, so you should always wrap accessing the Realm instance/objects in a using block and not use async code within that block. If you do need to run some async code (e.g. to wait for notifications or synchronization), you will need to install a context - for example, by using Nito.AsyncEx.

In terms of using Realm for server-side rendering, it has both benefits and drawbacks. One benefit is that it optimizes transfer of data from Atlas and caches that data locally. This means if you get a lot of client requests for the same objects, you’ll be able to respond much faster than if you had to query MongoDB every time. There are two downsides to consider though:

  1. Initial responses may be slower because Realm needs to synchronize all complete objects matching a request. For comparison, querying MongoDB directly allows you to select just the fields you need and also limit the response size - e.g. “give me just the names of the first 20 of your friends” will complete faster than asking Realm to synchronize all your friends locally. That being said, subsequent requests on the same dataset will complete a lot faster with Realm than if you had to synchronize with MongoDB.
  2. Data persisted in Realm will eventually get synchronized to Atlas, which means if you have multiple webservers handling requests, you may need to be careful to ensure consistent behavior on the client side. This can be achieved either using sticky sessions to make sure requests from the same client go to the same server or by waiting for synchronization before and after every request (which will slow down response times).
2 Likes

I see, then what about user management? I want to allow user registration / log in, but as I understand this info is stored in mongodb-realm folder which is one folder near my website files, can it manage different users from different devices? If so, how?

@nirinchev what’s the point of having multiple users if it’s a website with normal Realm? It will always use the last logged in user’s credentials, right? Or should I check in AllUsers and manage access through custom data etc? Because now when I log in, the website shows my credentials on any other device whether I logged in there or not

Hm… user management is going to be somewhat tricky, particularly with load balanced sites. My guess is that you still want to roll out your own authentication mechanism - e.g. when a client logs in, you relay their credentials to Atlas App Services and obtain a user. Then, you issue an access and refresh tokens signed with your own keys and send those to the client device. When a client device makes a request, you find the user in app.AllUsers and then pass that user to the FlexibleSyncConfiguration.

Now the challenge comes when we introduce load balancing. Then a client would not be guaranteed to reach the same web server on every request, meaning a user that logged in on server A would not be available in app.AllUsers on server B. There are two approaches for this:

  1. Add some routing information to the access token and use that for load balancing - then each user will be assigned exactly one web server. The challenge with this is that if a web server goes down, users will experience this as an outage or will need to relogin.
  2. Store the Atlas App services refresh token in some centralized storage location so that all web servers can look it up if they receive a request from a user they don’t know.

Note that the current SDK API are not a great fit for this use case, but we’d be happy to make small adjustments to support it. Notably, right now, app.AllUsers returns an array, which would be expensive if you have thousands of users. Similarly, we don’t have an API to create a user from a refresh token, but that can easily be added.

1 Like

Yes, that’s what I thought too, it would be really great if you do some APIs to make these things easier, like switching to another user without getting the whole list for instance as you mentioned. But thank you, this is valuable information.