Syncing data for offline usage is simple. The native app only needs to download a snapshot of data which can be queried when the device is offline. But syncing back newly created and modified entities to a cloud based backend is really, really tricky.
In a current project we’ve found out that the following architectual rules lead to a clear implementation.
All your business is local
The whole app has to work locally. Each controller and service only reads and modifies local data. There are two exceptions: A dedicated sync service and an authentication service which handles the session token. Only these two services may communicate with the backend.
Client based identity generation
The unique identity of an entity will be generated by the app using an UUID generator. The backend will use this UUID as primary key for the received entity as well. The big advantage of this approach is simplicity: You don’t have to reassign entity ids after the sync process has completed.
Track changes using commands
If data is changed the local representation of the affected entity will be modified. In addition the responsible change command will be tracked in a separate database table. This pattern is called command sourcing. When the sync service is requested to sync back the data to the backend, it will iterate over the command table and send all the stored commands in the order of their appearance.
The backend should perform suitable validation of the command data, because the client request may not be trustworthy. In contrast to an event, a command might be rejected.
Quite simple, but the real interesting point is conflict resolution. This will be the topic for my next blog post.