How to sync data for an offline-first app

I’m curious as to what’s the recommended pattern to build an offline-first app with Meteor today.

The use case is we’re building a small app that’s used as a field notes tool, where connectivity would be intermittent. The app needs to work offline and store data, and sync data whenever there is an internet connection. If there is a server-side update to the same dataset, it should also be synced and available if the device goes offline again.

I’ve looked at GroundDB and given that it’s not been updated in a while, what’s the best way to use mini-mongo and pub/sub when online, but still have offline data available with disconnected?

Data synchronisation and resolution is an … entire industry. What if you have an update for the same data on both server and offline app? You need a resolution and while you do the resolution, another user changes it again … It is really complicated to have a proper sync and create an environment with a single source of truth.

Anyway, I think you could best make use of RealmDB for offline which now is also supported by Atlas. In most cases people end up with a push/pull data system and not a real sync. If that satisfies you, it is very easy to pull data with a method into your local (offline) RealmDB, do what you do and then upsert the object back to the server. While you upsert, you can compare the changes and ask the user to confirm overwriting of certain fields or the entire thing.
RealmDB has a similar API as Mongo and it is very easy to work with and it supports schemas and it is free and probably the most advanced Javascript ready DB for mobile. No Minimongo pub/sub.

I think you could easily get away with something like Dexie.js:

I didn’t introduce Dexie.js into my app yet, but I think I will. Its API is really neat, whereas IndexedDB’s is a farce or a horror movie, I couldn’t make up my mind yet. Of course what @paulishca says is very true, synchronization can be trivial or it can be nightmarishly complicated – it all depends on your use case.