Docs Menu

Choose Your Sync Mode

On this page

  • Overview
  • Partition-Based Sync
  • Flexible Sync

When you enable Atlas Device Sync, you must specify a Device Sync mode for your App. The Device Sync mode determines how users can access data from the Atlas App Services SDK in the client app. App Services offers two Device Sync modes:

  • Partition-Based Sync
  • Flexible Sync
Note

To switch between Sync modes, you must terminate & re-enable Sync, which triggers a client reset.

Partition-Based Sync works best for applications where a subset of the documents in a synced cluster are related and have the same read/write permissions for a given user. Those documents form a partition.

In Partition-Based Sync, you define a partition key whose value determines whether the user can read or write a document. Atlas App Services evaluates a set of rules to determine whether users can read or write to a given partition. App Services directly maps a partition to individual synced .realm files. Each object in a synced realm has a corresponding document in the partition.

Choose Partition-Based Sync when:

  • You can define a single field and use an equality query to determine which documents to sync
  • Your data structure supports permissions at a partition level
  • You want to release a production app quickly, while Flexible Sync is still in preview
Example

Partition-Based Sync might be a good fit for an inventory management application. If you use store_number as the partition key, each store can read and write documents pertaining to its inventory.

An example of the permissions for this type of app might be:

{ "%%partition": "Store 42" }

Store employees could have read and write access to documents whose store number is Store 42.

Customers, meanwhile, could have read-only access to store inventory.

In the client, you pass a value for the partition key when opening a synced realm. App Services then syncs objects whose partition key value matches the value passed in from the client application.

Example

Based on the store inventory example above, the SDK might pass in store42 as the partitionValue in the sync configuration. This would sync any InventoryItem whose partitionValue was store42.

You can use custom user data to indicate whether a logged-in user is a store employee or a customer. Store employees would have read and write permission for the store42 data set, while customers would have only read permission for the same data set.

const config = {
schema: [InventoryItem], // predefined schema
sync: {
user: app.currentUser, // already logged in user
partitionValue: "store42",
},
};
try {
const realm = await App Services.open(config);
realm.close();
} catch (err) {
console.error("failed to open realm", err.message);
}
Note
Flexible Sync Prerequisites

Enabling Flexible Sync in Your App Services Application requires a non-sharded MongoDB Atlas cluster running MongoDB 5.0 or greater

Flexible Sync works best for applications that need to define a query in the client application, and Sync only the documents that match the query. App Services translates those documents to objects in the client application, making it easy to work with objects in your app. Additionally, it allows permissions to be applied on a per-document basis.

In Flexible Sync, you define a set of queryable fields that you can query from the client application. You can then subscribe to queries on those fields from the client application. When a client starts a Sync session, App Services evaluates rules to determine which documents in the query the user can access. App Services maps the documents that a user can access to a synced .realm file. Each object in a synced realm gets translated to a corresponding document in MongoDB Atlas.

Choose Flexible Sync when:

  • You need to create expressive query and result sets using a broad range of queries on up to 10 fields
  • You want to apply permissions at the document level
  • You need a flexible permissioning system to apply more granular permissions
Example

Flexible Sync might be a good fit for software to manage a medical provider's office. The combination of queryable fields and granular permissions means you could write software where:

  • Physicians have read and write access to a patient's health history, and can add notes for visits, new medications, and instructions. However, a physician might not have access to billing data or a patient's social security number.
  • Billing specialists have access to a specific subset of patient data, such as dates and procedure codes, but don't have access to physician's notes, prescription history, or other patient health data.
  • Patients have read access to their own history, such as physician notes, medications, and instructions. They can also view billing information, such as procedure dates, costs, and payment history. However, a patient would not have write access to any of this data.

To achieve this level of permission granularity, you might have different collections storing patient information:

  • A Patient_History collection storing provider notes, medications, and other patient health data
  • A Billing collection storing dates of procedures, billing codes, insurance information, and other relevant data

The permissions for these two collections might look similar to:

{
"Patient_History": {
"roles": [
{
name: "provider",
applyWhen: { "%%user.custom_data.isProvider": true},
read: {}, // evaluates to the same as %%true
write: {}
},
{
name: "self",
applyWhen: {},
read: {"patient_id": "%%user.id"},
write: false
}
]
},
"Billing": {
"roles": [
{
name: "billingSpecialist",
applyWhen: { "%%user.custom_data.isBillingSpecialist": true},
read: {}, // evaluates to the same as %%true
write: {}
},
{
name: "self",
applyWhen: {},
read: {"patient_id": "%%user.id"},
write: false
}
]
}
}

The queryable fields might be patient_id and procedure_date. This would enable the client application to query for specific patients, while billing specialists could query for visits within a time window, such as 30 days.

In the client, you subscribe to a set of queries to determine the data to sync. App Services then syncs objects that match the query, where the logged-in user has permission to read or read and write the data.

Example

Based on the store medical provider's office example above, the SDK might subscribe to a query on a specific patient's ID and procedure date range. This would sync any objects that matched the query, where the user has the appropriate permissions.

You can use custom user data to indicate a logged-in user's role. A provider would have access to data in the Patient_History collection, while a billingSpecialist would have access to data in the Billing collection. The SDK query subscription doesn't need any knowledge of this; Flexible Sync handles it automatically by applying the permissions to data that matches the query.

const patientVisits = realm.objects("Visit");
const patientAndTimeWindow = patientVisits.filtered(
'id == "507f191e810c19729de860ea" && procedureDate > new Date("Wed Oct 18 2020 12:00:00 GMT+0000 (UTC)")'
);
const subscriptions = realm.subscriptions;
subscriptions.update((mutableSubs) => {
mutableSubs.add(patientAndTimeWindow, {
name: "patientAndTimeWindow",
});
});
←  Data Access PatternsFlexible Sync →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.