Questions about the correct way to use Realm and the Realtime functionality

Good morning/Good afternoon/Good evening everyone

Firstly, I apologize for the inconvenience.

I have a question regarding the use of Realm and what would be the best way to work with it.

We currently have a project that uses Realm to use data in real time and this same app uses the offline first strategy.

We currently have an issue with the real-time update feature.
As we follow the clean arch structure, we use a mapper that transforms the Realm object into an application object and we trigger the information using the streams feature to propagate the records, but as I said previously, we lose the real-time update feature, After changing the project to use Realm objects directly, we no longer had this problem.

Then I had some doubts regarding the use of Realm in the project, they would be as follows:

1 - is it mandatory to work directly with Realm objects to be able to have the real-time synchronization feature?
As we use the concept of datasources, if we need to change the database it would be easier to change.
Following the strategy I mentioned, could you not work directly with the Realm object directly in the project?

2 - for every query that I need to have the real-time resource, is it necessary to register the same query again?
Is there any other type of strategy to have this functionality?

Thank you very much for everyone’s support.

Why wouldn’t you want to do that?

A Realm Results objects is a fine datasource. As the database changes, so do the results, and via notifications, the UI can be updated as well.

Not sure I understand the question. What does “work directly” mean code-wise?

That depends. A results object reflects the state of the underlying data and running a query is what populates that results object. Suppose a query is run to show all restaurants with one mile of your location. As the app is running and you move about your city, restaurants meet that query will be added (within 1 mile) and restaurants will be removed that fall outside the query parameters (outside 1 mile). If the results are stored at a high level within your app, as an app-level var or within the main class app for instance, that Results object will not go out of scope so it would not need to be re-registered.

1 Like

Good afternoon!

Thank you very much for responding.

Regarding the doubts that I left and that generated more doubts for you, I will leave them below:

We recently had a meeting with our Solutions Architect and got into a debate about the options for data consumption tools in the application that is under development (it is currently already being integrated with Realm due to our backend services using the resources of MongoDB).

One of the questions he asked us was the following:
To maintain information reactively to changes, how does Realm work?
We explained to him that, for it to work correctly, it would be necessary to work only with the objects provided by Realm, that is, an object specific to the app could not be used to have realtime functionality.
In the first attempt to use it, we used the concept of data source mappers, created an app’s own object and made the necessary transformations to use the returned data (Realm object mapper for application object) and propagate it through streams.
We did it this way, so that if the data source was changed (changing from Realm to an api, or Firebase for example), there would be a change only in the datasource, that is, it would not affect the other layers below.
On the day of the Realm presentation with Flutter (Youtube/LinkedIn), I asked a question related to this and based on the answer, I was asked to use the Realm object directly in the project.

We currently had a problem regarding some business rules between the application and the web system (which work integrated), which involved the real-time update feature.
We were asked why we were working directly with Realm objects in the project, where we explained that to have the real-time synchronization feature, it would be necessary to use it in the way indicated in the documentation and indicated by the library’s development team.

We explained to him that at the beginning of the project, we used the concept of mappers, but over time we saw that we lost the ability for data to be updated in real time.
As we changed the project to transport Realm objects, the feature worked correctly, that is, the data linked to the Realm object is transmitted to the interface (UI), domain layers (usecases and repositories), data (repository implementation) and datasource (Realm).

About your question:

Not sure I understand the question. What does “work directly” mean code-wise?

Is it really mandatory to work only with Realm objects to have real-time synchronization?
Why do I ask this question?
As our architect asked about how to use Realm in the project and our explanation (to have the realtime feature it is necessary to work directly with the objects provided by the library), we were asked if this would not generate high coupling in the project?
If the data source were changed (api or another library for example), we would need to remove the Realm usage references from the project, and only then carry out the data consumption operations from this new data source.

Again, thank you very much for responding and I’m sorry for leaving such big questions, as I’m new to using Realm and Flutter, I had these doubts.
As there was an indication to ask questions about Realm (through Github), I came to leave these questions.

I thought it would be better to ask the creators about the correct way to work with the library, rather than deducing what can be done and not having an assertive answer.

Thanks for the additional information. I will match your big question with a big answer :wink:

This meanders a little but really comes down to whether there is a need to decouple the data, a and if so, at what cost.

(skip to TL;DR to avoid this wall of text)

After coding for 45+ years now, I ‘get’ the concept and purpose of decoupling your project code from your datasource, and have done it many times.

Back in the day, when we had different flavors of SQL, it made sense. However, in many cases today that concept is very difficult to put into practice unless you make everything as ‘generic’ as possible when then bypasses the features of the database you’ve selected.

In many cases a database is not just a dumb datastore - databases are selected because of how it works with that data and the additional features that database provides - like Realms “live” objects.

I am intimately familiar with Firebase as well as Realm so allow me to provide an example.

Firebase and Realm are radically different. Right up front, Realm is an offline first database which provides syncing. Firebase on the other hand is a very much online-first database with some offline persistence (to handle brief interruptions in connection status)

Firebase has no concept of ‘live’ objects - the data is static unless there’s an update from the server (or an event). Whereas Realm objects are live and dynamic, always reflecting the status of the underlying data regardless of where that change came from.

So, what does that mean?

If you’ve selected Realm as your database and craft an app around the capability of “live” (i.e. dynamic) objects, you’re going to be hard pressed to adapt that to Firebase as just doesn’t do that. It would require total re-think of the app logic as well as a re-write of pretty much everything dealing with that data.

More importantly, when designing an app (with Realm), that design will leverage features like forward and inverse relationships, embedded objects, and the queries, objects and schema will reflect that functionality. Firebase doesn’t have relationships, schema (it’s schema-less!) or even objects! It’s a totally different NoSQL approach to working with data. Again, it would require a massive do-over.

My messaging is this - if separation of code from the underlying database is a requirement, it can be done. Look at Apple’s CoreData - it can be backed by a number of underlying sources. But… look at CoreData, it’s a massive effort! I don’t think I would want to build entire persistance framework into my project ‘just in case’ we switch data sources - even at that, which datasources? There are a lot.

For clarity. IMO Firebase is an awesome product, so is Realm. They serve different purposes and have radically different implementations.

I have transitioned many projects from and to a variety of databases and in general, if the datasource is changed, no matter how much effort was put into decoupling it, it’s a massive re-write and an many cases starting over; re-thinking everything about that data, relationships etc. Even though Realm is backed by NoSQL, the Realm front end is a very different approach to NoSQL than say Firebase Firestore is.

TL;DR

My suggestion is to think about the features you want and select a database based on that. Then, create a basic To-Do app - keep it simple, implement Adding and persisting ToDo’s, edit them and delete. Create a ‘relationship’ from one to do to another. Then, port it to a different database.

That process is often very revealing with a minimal amount of effort and time. It will help you gauge the complexity of the layer needed to decouple your code from the datasource or if you want to leverage the features (Realm) offers.

Yes. That’s one of the features Realm offers. If you can do without that feature or implement it in some other fashion, that would make it a bit easier to move to another platform if necessary.

3 Likes

Good morning @Jay!

Again, thank you very much for responding.

I’m still very inexperienced, but with your explanation, I was able to understand very well the purpose and how Realm helps.

I’m sorry for extending the conversation too long.
Here in Brazil, teams use Firebase resources more (including me hahaha), and the way Realm works differs a lot from what I was used to.
Realm’s performance is actually much better than other services that exist (Firebase, Supabase), and as there was this question from the leadership, I came here to seek help and be able to better explain how Realm supports us.

I really apologize for bothering you and again, thank you very much for giving your time to help me and answer my questions.

My pleasure to help!

One other thing to note that may help in your discussions about Realm is the memory footprint.

Realm is incredibly memory friendly - huge datasets can be accessed and managed without really worrying about overloading a devices memory. Objects are lazily loaded and as long as you stick with with Realm functions and avoid high level Swift functions, the memory footprint is low impact.

Many other databases don’t handle data in the same way; Firebase for example relies on pagination to handle large datasets in the device - while that’s not a bad thing, it just doesn’t work in the same fashion as Realm so that adds another layer of complexity in attempting to create a generic environment.

I am very surprised that Firebase doesn’t outperform other databases. It’s a crazy-fast platform… however, Realm’s advantage is that is pulls data locally (it’s a local-first database!) and local data is always faster than the internet. Again, you’re selecting Realm because it’s performant and has features you want to use.

2 Likes