Sync Rules Best Practices

When it comes to implementing Sync Rules the best guiding principle is to sync only that which the user needs to have access to offline. The less data the user has to sync, the more performant the sync process will be. It is recommended that you first read the Sync Rules v2 documentation to familiarize yourself with the Sync Rules concepts.

Global Bucket

The global-bucket will typically be used to sync all master data models. If your data model was built using suggested best practices, your master data will also have the archived field so you can easily exclude archived data being synced.

<?xml version="1.0" encoding="UTF-8"?>
<sync version="2">
    <global-bucket>
        <!-- List all master data models within the global bucket -->
        <model name="location" />
        <!-- You can define a condition to only sync active/unarchived data: -->
        <model name="customer" condition="archived != true" />
    </global-bucket>
</sync>

Syncing the User Object

It is important to remember to explicitly sync the user object. This can be accomplished by defining a bucket that has the root of “self” as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<sync version="2">
    <bucket via="self">
    </bucket>
</sync>

User Role Buckets

In most cases your sync rules, and by extension the offline data access requirements, will be determined by the user roles of your application. It is therefore very common to have sync rules that are defined on a user role basis. You can define global buckets and object-specific buckets on a user role basis. Below is an example taken directly from the Sync Rules documentation for reference.

<?xml version="1.0" encoding="UTF-8"?>
<sync version="2">
    <!-- Sync the user object itself, required to access 'user' in the app. -->
    <bucket via="self">
        <!-- Also sync all messages that the user has sent or received. -->
        <has-many name="sent_messages" condition="archived != true" />
        <has-many name="received_messages" condition="archived != true" />
    </bucket>
  
    <!-- For non-admin users, sync specific data related to sites. -->
    <bucket via="self[role != 'admin']/sites[archived != true]">
        <has-many name="buildings" />
        <has-many name="rooms" />
        <has-many name="equipment" condition="in_use == true" />
    </bucket>
  
    <!-- For admin users, sync data for all sites. -->
    <global-bucket via="self[role == 'admin']">
        <model name="building" />
        <model name="room" />
        <model name="equipment" />
    </global-bucket>
  
    <!-- Some global data is synchronized to all users. -->
    <global-bucket>
        <model name="category" />
        <model name="tool_types" condition="archived != true" />
    </global-bucket>
</sync>

Assignment Based Sync Rules

In addition to role-based syncing, you may also have the need to sync data based on assignments. For example, a project team assigned to Project A likely should only have the need to access Project A. An example of assignment based logic is included below.

<?xml version="1.0" encoding="UTF-8"?>
<sync version="2">
    <!-- Within the bucket, you can sync assignments via the user -->
    <!-- In this example, the assignments are a join table, project_users, between users and projects -->
    <bucket via="self">
        <has-many name="project_users"  condition=”active == true” />
        <!-- Note: This requires the user object to have a has-many project_users relationship defined within the data model -->
        <!-- Note: You can optionally define conditions here. In this example only active assignments (project_users) will be synced -->
    </bucket>

    <!-- Sync the project object itself via the project_user join table by having project the bucket root -->
    <!-- Project-specific data can then be synced via the project -->
    <bucket via="self/project_users[active == true]/project">
        <!-- List all has-many objects off of the project -->
        <has-many name="photos" /><!-- Note: This has-many must be defined in the data model -->
    </bucket>
</sync>

Tips for Defining Sync Rules in Online-only Applications

For online applications that only make use of OnlineDB, there are a few cases where syncing data and using DB will be better for your app’s performance.

  1. Sync data that is consistently queried throughout the application, e.g., master data or a permissions model that determines what should be displayed to the end user.

  2. Sync data that has a large number of objects that will be queried. There are some caveats here and it is important to determine a smart sync strategy, e.g., user role, assignment, or condition based sync rules. Please keep in mind the sync rules bucket limitation and the Guidance around using sync rules listed in the documentation.