Choose Your Sync Mode
On this page
Overview
When you enable Realm Sync, you must specify a Sync mode for your Realm app. The Sync mode determines how users can access data from the MongoDB Realm SDK in the client app. Realm offers two Sync modes:
- Partition-Based Sync
- Flexible Sync (preview)
While Flexible Sync is in preview, you cannot use Flexible Sync & Partition-Based Sync in the same Realm app. You must decide which Realm Sync mode to use in a given application. To switch between Sync modes, you must terminate & re-enable Sync, which triggers a client reset.
Partition-Based Sync
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.
MongoDB Realm evaluates a set of rules
to determine whether users can read or write to a given partition. Realm
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
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. Realm then syncs objects whose partition key value matches the value passed in from the client application.
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 Realm.open(config); realm.close(); } catch (err) { console.error("failed to open realm", err.message); }
Flexible Sync
Flexible Sync is currently in preview. We encourage you to try out the feature and give feedback, but please be aware that:
- Configuration details may change.
- SDK API implementation details may change.
We do not recommend using Flexible Sync in production applications while it is still in preview.
Enabling Flexible Sync in Your Realm Application requires the following:
- A non-sharded MongoDB Atlas cluster running MongoDB 5.0 or greater
- A Realm app without Partition-Based Sync enabled. While Flexible Sync is in preview, you cannot use Flexible Sync & Partition-Based Sync in the same Realm app.
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. Realm 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, Realm
evaluates rules to determine
which documents in the query the user can access. Realm 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
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. Realm then syncs objects that match the query, where the logged-in user has permission to read or read and write the data.
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", }); });