Sync Rules v1 (deprecated)

Sync Rules v1 have been deprecated

Please use Sync Rules v2 instead.

To migrate to Sync rules v2, please use this migration guide.

Sync rules give developers the ability to determine programmatically what data should be sync to which devices. Sync rules are important in production applications, where devices should only store data that's needed for the app to work for security and performance reasons.

Developers can specify sync rules for their app by opening sync_rules.xml in OXIDE.

Details matter with sync rules

Sync Rules is an advanced feature where implementation details can have a significant impact on app performance, sync performance, as well as the design of your data model.

Please be sure to understand the constraints and implications of your sync rules before deploying them to an environment with active users.

Sync Rule Reprocessing

When changes to the sync rules are deployed to the backend, all data for that instance needs to be processed again to take the new sync rules into consideration. During sync rule reprocessing, your app will not be able to sync.

Basic Sync Rules Types

A developer can specify four types of sync rules:

  1. Rules for the user object

  2. Rules for globally-synced objects, called object

  3. Rules for has_many relationships

  4. Rules for belongs_to relationships

It is possible to use a condition in user, object and in has_many relationships to filter the objects that should be synced per device. This is particularly useful for apps where you'd like to sync objects with certain statuses, or are applying an archiving strategy for older objects.

Constraints

Please take note of the following constraints in sync rules:

  1. Apart from globally synced objects, you can only sync objects directly or indirectly to the user.

  2. You can sync any two nested relationships from the user. The single exception is userhas_manybelongs_to, which is not allowed. This means that many-to-many relationships with the user are not currently supported in sync rules.

  3. You cannot nest any relationships from a global object

  4. condition can be == (equal), != (not equal), > (greater than), < (less than), &gte; (greater than or equal), &lte; (less than or equal). Conditions can be used within has_many and object.

Examples: The basics

Sync everything (the default):

<?xml version="1.0" encoding="UTF-8"?>
<sync>

</sync>

The following example, on the other hand, synchronizes nothing except the user itself. As soon as the user type is referenced in the sync rules, all objects have to be explicitly specified.

<?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user">

  </user>
</sync>

Here is a more complicated example:

<?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user">
    <!-- Sites objects (per user) -->
    <!-- Can also use belongs_to instead of has_many -->
    <relationship has_many="sites">
      <!-- Can only use has_many here -->
      <!-- Cannot nest any deeper than 2 levels -->
      <relationship has_many="generals" />
      <relationship has_many="areas" />
      <relationship has_many="sub_areas" />
      <relationship has_many="element_groups" />
      <relationship has_many="elements" />
      <relationship has_many="conditions" />
      <relationship has_many="materials" />
      <relationship has_many="sync_photos" />
    </relationship>

    <!-- Template objects (global) -->

    <!-- These are always template objects -->
    <!-- Cannot nest anything inside these objects -->
    <object type="material_type" />
    <object type="joint_element" />
    <object type="joint_area" />

    <!-- These may be template objects, determined by the is_template flag -->
    <object type="area" condition="is_template == true" />
    <object type="sub_area" condition="is_template == true" />
    <object type="element_group" condition="is_template == true" />
    <object type="element" condition="is_template == true" />
    <object type="condition" condition="is_template == true" />
    <object type="general" condition="is_template == true" />
  </user>
</sync>

Conditions on user role:

<?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user" condition="role != 'admin'">
    <!-- Sync by relationship for normal users -->
    <relationship has_many="sites">
      <relationship has_many="generals" />
      <relationship has_many="areas" />
      <relationship has_many="sub_areas" />
    </relationship>
  </user>

  <user type="user" condition="role == 'admin'">
    <!-- Sync all objects for admins -->
    <object type="general" />
    <object type="area" />
    <object type="sub_area" />
  </user>
</sync>

Examples: Real-life applications

In this section we will show you a few real-life examples of how sync rules can be used.

Simple Field Service App

Here's a sample data model for a simple field service app.

This is an example of a "sync rule compatible" data model, with nested has_many relationships from the Technician (user) object. In this case, all of the Job Cards belonging to the Technician and all of their Line Items and Photos can be synced to the device.

In addition, it would be possible to sync all Products globally.

Here's an example of corresponding sync rules for the data model above:

<?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user">
    <relationship has_many="job_cards">
      <!-- Can only use has_many here -->
      <!-- Cannot nest any deeper than 2 levels -->
      <relationship has_many="line_items" />
      <relationship has_many="photos" />
    </relationship>

    <!-- Global objects -->
    <!-- Note: You cannot nest anything inside global objects -->
    <object type="product" />
  </user>
</sync>

Time Study App

Here's a sample data model for a simple time study app.

This is another example of a "sync rule compatible" data model for a time-tracking app where the User belongs-to an Operation, which has multiple Observations. In this case all the operations from the User's current operation can be synced.

Here are the corresponding sync rules:

<?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user">
    <relationship belongs_to="operation">
      <!-- Can only use has_many here -->
      <relationship has_many="observations" />
    </relationship>
  </user>
</sync>

Syncing everything (default)

The default for every app is to sync all data to all devices:

<?xml version="1.0" encoding="UTF-8"?>
<sync>

</sync>

Considerations when an app doesn't have sync rules

It is desirable to sync as little data to a device as possible due to performance and security reasons.

Not specifying sync rules means that all users will get all data. This is often inadequate in production where data volumes will grow linearly over time, scaled by the number of active devices. Having more data synced to an app impacts the performance of queries, and also adds general memory overhead to the app.

Sync only the user object

The following example, on the other hand, synchronizes nothing except the user itself. This is not useful in practice but illustrates how sync rules work. As soon as the user type is referenced in the sync rules, all objects have to be explicitly specified.

<?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user">

  </user>
</sync>

A complicated example:

Here is a more complicated example that shows all the constraints of sync rules:

<?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user">
    <!-- Sites objects (per user) -->
    <!-- Can also use belongs_to instead of has_many -->
    <relationship has_many="job_card">
      <!-- Can only use has_many here -->
      <!-- Cannot nest any deeper than 2 levels -->
      <relationship has_many="line_items" />
      <relationship has_many="sync_photos" />
    </relationship>

    <relationship belongs_to="site">
      <!-- Cannot nest any deeper than 2 levels -->
      <relationship has_many="areas" />
      <relationship has_many="sub_areas" />
      <relationship has_many="materials" />
    </relationship>

    <!-- Global objects -->

    <!-- These objects are synced to all devices -->
    <!-- Note: You cannot nest anything inside these objects -->
    <object type="material_type" />
    <object type="joint_element" />

    <!-- Global objects can include conditions: -->
    <object type="area" condition="archived != true" />
    <object type="order" condition="status &lt;= 2" />

  </user>
</sync>

User roles

It is possible to have multiple user sync rules blocks with different conditions to account for user roles:

 <?xml version="1.0" encoding="UTF-8"?>
<sync>
  <user type="user" condition="role != 'admin'">
    <!-- Sync by relationship for normal users -->
    <relationship belongs_to="site">
      <relationship belongs_to="company" />
      <relationship has_many="areas" />
      <relationship has_many="sub_areas" />
      <relationship has_many="materials" />
    </relationship>
  </user>

  <user type="user" condition="role == 'admin'">
    <!-- Sync all objects for admins -->
    <object type="general" />
    <object type="area" />
    <object type="sub_area" />
  </user>
</sync>

Developers Notes

Here are a few final notes on sync rules for developers:

  • Once sync rules have been deployed for an app, it will become critically important to update the rules when new models are added to the data model, or if model or relationship names change. Failing to do so will result in queries not showing the necessary data in the view, or logic in the JS failing.

  • Sync rules affect what data can be accessed in the app via DB. OnlineDB is unaffected by sync rules.

  • Sync rules constraints have a big impact on data model design. It is often useful to create "sync relationships" which are only used for sync rules, but have no other meaning in the data model.

Guidance around using sync rules

A general rule is to sync only the data that is applicable to a specific app. The fewer data synced, the more performant the app will be in general:

  • Fewer than 10k objects on a device is ideal.

  • Up to 50k objects synced to a device should work but needs to be tested properly. At these data volumes, the app becomes sensitive to poorly-written and unindexed queries. Be sure to monitor the DB size for increases (in the app diagnostics) to prevent unforeseen performance degradations.

  • Up to 500k objects synced to a device can work, but even with performant queries the sync performance will become slow. This will be exacerbated if there are a large number of users syncing the same data or if the data changes often. Strongly consider using aggressive archiving strategies, or OnlineDB.

Last updated