Sync Settings
On this page
This page explains the settings available when you enable or configure Device Sync.
Available Settings
Cluster to Sync
The name of the linked Atlas cluster data source where you want to store your synced data.
You cannot modify this field while Device Sync is enabled. You must terminate Sync before you can select a different cluster.
Note
Data Source Requirements for Device Sync
To enable Device Sync, your App Services App must have at least one linked data source that meets the following requirements:
A non-sharded MongoDB Atlas cluster running MongoDB 5.0 or later.
Cluster cannot be a serverless instance or Federated database instance. Refer to Data Source Limitations.
Sync Type
Important
Sync Type is Only Available for Partition-Based Sync Apps
The ability to select your app's Sync Type is only available for organizations with at least one existing Partition-Based Sync app in their project.
Partition-Based Sync has been deprecated and is disallowed for new Sync configurations. Instead, all new Sync configurations automatically default to the recommended Flexible Sync mode.
When you enable Device Sync, you can select one of the following Sync modes:
Flexible Sync lets you define a query in the client and sync only the objects that match the query. With client-side subscriptions, client applications can:
Maintain queries
React to changes
Add, change, or delete queries
Flexible Sync is the only mode available for new Sync configurations.
Partition-Based Sync is an older Sync mode that has been deprecated and is disallowed for new Sync configurations.
If you have an existing app that already uses the older Partition-Based Sync, we highly recommend that you migrate to Flexible Sync. Migration is an automatic process that doesn't require any changes to your client app code except upgrading SDK versions. For more information, refer to Migrate Device Sync Modes.
You cannot change the Sync type while Device Sync is enabled. You must terminate or pause Sync before you can make your changes.
Development Mode
Development Mode is a configuration setting that allows Device Sync to infer and update schemas based on client-side data models. This streamlines development, but should not be used in production.
Development Mode speeds up development by allowing you to design schemas directly in client application code.
When you sync a realm, Atlas App Services maps every synced object type to its own collection in the database specified by Database Name (Development Mode Only). If you update the object model on the client side, App Services updates the collection schema to match. This lets you update objects in your client code as you develop your app.
You can use data access rules with Development Mode. Note that schema changes ignore data access rules. This means that any client can update the backend schema by changing the client model.
To learn more about how the Realm Object Schemas map to the App Services Schemas when using Development Mode, refer to Data Model Mapping.
For more information about modifying synced object schemas, see: Update Your Data Model.
Important
Disable Development Mode for Production Apps
Development Mode is a development utility that is not suitable for production use. Make sure that you turn off Development Mode before you make your app accessible in a production environment.
Breaking Changes
App Services Apps in Development Mode that were created after September 13, 2023 can make breaking changes to synced object schemas from client code.
If your App was created before September 13, 2023, you can contact support to enable this feature.
Prerequisites
App Services App created after September 13, 2023
MongoDB 5.0 or later for Flexible Sync compatibility
Minimum SDK version:
Realm C++ SDK v1.0.0
Realm Flutter SDK v1.6.0
Realm Java SDK v10.16.2
Realm Kotlin SDK v11.1.1
Realm .NET SDK v11.6.0
Realm Node.js SDK v12.2.0
Realm React Native SDK v12.2.0
Realm Swift SDK v10.42.2
Note
Apps created before September 13, 2023
For Apps created before September 13, 2023, you need to update your object schema in the App Services UI. For details, see Update Your Data Model
To make a breaking change from client code:
Delete your local realm and data. This will not affect data synced to the backend. Local changes that have not been synced will be removed and are unrecoverable.
Change your local object model.
Open a realm with your updated object model.
Run your client app to sync your changes to the backend.
To delete a Realm file use the Realm SDK-specific methods:
Side Effects of Enabling Development Mode
Enabling Development Mode has two side effects:
Enabling anonymous authentication.
Disabling deployment drafts.
If your app does not need anonymous authentication, you may want to disable it after enabling Development Mode.
You cannot re-enable deployment drafts in the UI until Development Mode is disabled. However, you can still manually create deployment drafts through the CLI or the Admin API.
Database Name (Development Mode Only)
When you enable Development Mode, you specify a database to store synced objects. App Services creates new collections in this Development Mode database for every type of synced object.
Example
Specify a Development Mode database of myapp
. Your iOS client has a
Person
model. You sync a realm that contains an instance of the
Person
object. Development Mode creates a server-side schema associated
with the model. The object syncs to the myapp.Person
collection.
App Services continues creating new server-side schemas and collections
for each new object type. If you later add a Dog
object, that object
will sync to a new myapp.Dog
collection that App Services will
create.
Queryable Fields
When you configure Flexible Sync, you specify field names that your client application can query in a Flexible Sync subscription. Fields that can be used in a subscription query are called queryable fields.
Example
In a to-do list app, you might set assignee
or owner
as queryable fields. On the client side, you can then query for tasks
whose assignee
or owner
matches the logged-in user.
Queryable Field Scopes
Queryable fields apply to a scope you designate when you configure them. The two available scopes are:
Global queryable fields: scoped across all collections in an App's Schema.
Collection queryable fields: scoped to a single collection in the App.
Scoping a queryable field to a specific collection reduces the amount of backing Atlas storage required to store Sync metadata.
You can use rules and permissions to configure more granular access control on a per-collection basis. You can define collection-level rules and permissions for both global and collection queryable fields.
Configure Queryable Fields
You can automatically specify queryable fields by enabling Development Mode. Fields that appear in client queries while using Development mode are automatically added as collection queryable fields for the collection being queried.
The field names you provide are arbitrary strings. If an object type has a field whose name matches a field name you provided (and meets other eligibility criteria), that field becomes available to Device Sync to query.
Configure Indexed Queryable Fields
You may only add or remove an indexed queryable field when Device Sync is not enabled. If Device Sync is already running in your App, you must terminate Sync, and configure the indexed queryable field when you re-enable it.
This causes client resets for any client attempting to reconnect after re-enabling Sync.
Eligible Field Types
Flexible Sync only supports top-level primitive fields with a scalar type as queryable fields. You can also include arrays of these primitives as queryable fields. Flexible Sync does not support embedded objects or arrays of objects as queryable fields.
Indexed queryable fields support a subset of data types. Your indexed
queryable field can be one of: int64
, string
, ObjectId
, UUID
.
Tip
See also: Realm Query Language - Flexible Sync Limitations
For information on the queries you can perform on these fields, see: Flexible Sync RQL Limitations
Reserved Field Names
App Services reserves some keywords for the Realm Query Language and other purposes. You cannot use reserved keywords as field names.
App Services reserves the following keywords with any capitalization:
|
|
|
Example
You cannot use descending
, Descending
, DESCENDING
, or
DeScEnDiNG
as a field name.
App Services also reserves the following keywords with the given exact capitalization:
|
|
|
Example
You cannot use true
or TRUE
, since both capitalizations are
specifically reserved, but you can use True
or tRUE
as a field name.
Performance and Storage
Each queryable field adds additional metadata storage to your Atlas cluster and may lead to degraded write performance. You should have as few queryable fields as needed by your application, and scope them to the minimum number of collections required.
Many apps find a good balance between storage usage and query flexibility with at most 10 queryable fields applying to any single collection. For example, if you have 3 global queryable fields and 7 collection queryable fields, you have 10 queryable fields that apply to the collection.
If you have a field that you only want to query in one collection, but it
is configured as a global queryable field, this unnecessarily consumes
Atlas storage space. For example, if you have a user
field in every
collection, but you only use it for Sync queries in one collection, scoping
that as a collection queryable field reduces storage requirements. Reducing
the scope means that Sync does not have to maintain metadata for that field
for the other collections where you are not querying on the user
field.
If you need to reduce storage usage or improve performance, you can remove unneeded queryable fields from your App. However, be aware of the consequences of adding or removing queryable fields. For more information, refer to Consequences of Adding or Removing Queryable Fields.
For additional considerations, refer to optimizing performance and storage when using Flexible Sync.
Indexed Queryable Fields
You can improve performance for certain types of workloads by adding an indexed queryable field. An indexed queryable field is a global queryable field that can be queried on more efficiently, providing improved Sync performance. You can designate one global queryable field as an indexed queryable field.
Indexing a queryable field improves performance for simple queries on a
single field, such as {“store_id”: 1}
or
{“user_id”: “641374b03725038381d2e1fb”}
.
The indexed queryable field must appear in the schemas of all of your
Sync collections, and it must use the same valid data type. For example,
if your indexed queryable field is store_id
, it must appear in all of
the collections you sync, and it must be the same valid type in all the
collections. For more information about eligible field types, refer to
Eligible Field Types.
You Can't Change Indexed Queryable Field Values on the Client
After you configure an indexed queryable field, client devices cannot
update an existing object's indexed queryable field value. For example,
if your indexed queryable field is store_id
, the client cannot change
this value directly. Changing it from the client is not supported because
it may conflict with other updates made to the object in the same timeframe.
If you attempt to change an indexed queryable field's value on the device,
this triggers a compensating write error. For more information about this
error and the behavior it entails, refer to ErrorCompensatingWrite
in
the Flexible Sync Errors documentation.
You can still change this value directly in the Atlas database.
Warning
Changing an object's indexed queryable field value through Atlas may overwrite concurrent client updates to the object.
Client-Side Queries on Indexed Queryable Fields
When your app uses an indexed queryable field, client-side queries in a
Flexible Sync subscription must include the indexed queryable field using
an ==
or IN
comparison against a constant at least once. For
example, user_id == 641374b03725038381d2e1fb
or store_id IN {1,2,3}
.
You can optionally include an AND
comparison as long as the indexed
queryable field is directly compared against a constant using ==
or IN
at least once. For example, store_id IN {1,2,3} AND region=="Northeast"
or store_id == 1 AND (active_promotions < 5 OR num_employees < 10)
.
Invalid Flexible Sync queries on an indexed queryable field include queries where:
The indexed queryable field does not use
AND
with the rest of the query. For examplestore_id IN {1,2,3} OR region=="Northeast"
is invalid because it usesOR
instead ofAND
. Similarly,store_id == 1 AND active_promotions < 5 OR num_employees < 10
is invalid because theAND
only applies to the term next to it, not the entire query.The indexed queryable field is not used in an equality operator. For example
store_id > 2 AND region=="Northeast"
is invalid because it uses only the>
operator with the indexed queryable field and does not have an equality comparison.The query is missing the indexed queryable field entirely. For example,
region=="Northeast"
ortruepredicate
are invalid because they do not contain the indexed queryable field.
Consequences of Adding or Removing Queryable Fields
You can update your Sync configuration to add or remove queryable field names while Sync is enabled, but be aware of the following:
When you add a queryable field, devices can only sync on that field once the device has caught up to the point in time in Device Sync History where the field was added.
When you remove a queryable field, any devices still using that field will have their Device Sync session dropped and must perform a client reset. Clients not using the removed field won't receive any errors. To avoid triggering a client reset when you remove the queryable field, you should first remove usage of that field on the client-side.
If you terminate Sync before adding or removing queryable fields, these considerations do not apply. However, terminating Sync does trigger a client reset for any client that has Synced with your App.
Permissions
Atlas Device Sync enforces role-based data access rules for all requests to a synced cluster. Rules are dynamic JSON expressions that determine a user's ability to sync, view, and modify data.
For details, see Role-based Permissions.
Data Ingest
Data Ingest is a sync strategy for applications with heavy client-side insert-only workloads. You can enable it for one or more collections. It supports writing to any collection type, including an Atlas time-series collection.
For example, an IoT app that frequently logs sensor data has a significant write workload and no read workload. The device may also be offline for extended periods of time. Data Ingest bypasses some of the processing required for bi-directional sync, significantly improving write speed to an Atlas collection.
Other use cases include writing immutable data, such as invoices from a retail app, or logging application events, neither of which requires conflict resolution.
You can apply Data Ingest to individual collections. This means your app can use Data Ingest to write some data, but bi-directional Flexible Sync on other collections.
Data Ingest collections are only for writing data. You cannot use Flexible Sync queries against these collections. Instead, use Connect to MongoDB Data Sources.
After you have enabled Data Ingest, you implement it in the client app via the client SDKs. Currently, the following Realm SDKs support Data Ingest:
C++ SDK: Stream Data to Atlas - C++ SDK
Flutter SDK: Stream Data to Atlas - Flutter SDK
Kotlin SDK: Stream Data to Atlas - Kotlin SDK
.NET SDK: Unidirectional Data Ingest - .NET SDK
Node.js SDK: Define an Asymmetric Object
React Native SDK: Define an Asymmetric Object
Swift SDK: Stream Data to Atlas - Swift SDK
Atlas Device Sync completely manages the lifecycle of this data. It is maintained on the device until Data Ingest synchronization is complete, and then removed from the device.
Client Max Offline Time
Client Maximum Offline Time determines how long the client can be offline between sync sessions. Changing this value enables you to balance offline access with storage used in the synced Atlas cluster. For more information, refer to Client Maximum Offline Time.
Client Recovery
Client Recovery enables the client to attempt to automatically perform a client reset while recovering data on the device. For more information, refer to Recover Unsynced Changes.
Sync Configuration File Reference
You can find the Sync configuration file for your application in the sync
directory of an exported app:
app/ └── sync/ └── config.json
For example, the following Sync configuration applies to apps using Flexible Sync.
{ "type": "flexible", "development_mode_enabled": <Boolean>, "service_name": "<Data Source Name>", "database_name": "<Development Mode Database Name>", "state": <"enabled" | "disabled">, "client_max_offline_days": <Number>, "is_recovery_mode_disabled": <Boolean>, "queryable_fields_names": [ <Array of String Field Names> ], "indexed_queryable_fields_names": [ <Array of String Field Names> ], "collection_queryable_fields_names": <Map[String][]String> "permissions": "<Deprecated, Do Not Use>" }
The deprecated permissions
field might still appear in your exported app's
configuration. That might indicate your app has not automatically migrated to
the unified rule system yet. Please avoid
deleting this field until your app has been migrated.
Sync Config Object
{ "type": "flexible", "development_mode_enabled": <Boolean>, "service_name": "<Data Source Name>", "database_name": "<Development Mode Database Name>", "state": <"enabled" | "disabled">, "client_max_offline_days": <Number>, "is_recovery_mode_disabled": <Boolean>, "queryable_fields_names": ["<Field Name>", ...], "indexed_queryable_fields_names": ["<Field Name>", ...], "collection_queryable_fields_names": { "<Collection Name>": ["<Field Name>", ...], ... } }
Field | Description |
---|---|
type string | The sync mode. There are two Sync modes: Flexible Sync and the older Partition-Based Sync. We recommend using Flexible Sync. For more information about Partition-Based Sync, refer to Partition-Based Sync. Valid Options for a Flexible Sync Configuration:
|
development_mode_enabled boolean | If true , Development Mode is enabled
for the application. While enabled, App Services automatically stores synced
objects in a specific database (specified in database_name ) and
mirrors objects types in that database's collection schemas. |
service_name string | The name of the Atlas cluster data source
to sync. You cannot use sync with a serverless instance. |
database_name string | The name of a database in the synced cluster where App Services stores data in
Development Mode. App Services automatically
generates a schema for each synced type and maps each object type to a
collection within the database. |
state string | The current state of the sync protocol for the application. Valid Options:
|
client_max_offline_days number | The number of days that the backend compaction
process waits before aggressively pruning metadata that some clients
require to synchronize from an old version of a realm. |
is_recovery_mode_disabled boolean | If false , Recovery Mode is enabled
for the application. While enabled, Realm SDKs that support this feature
attempt to recover unsynced changes upon performing a client reset.
Recovery mode is enabled by default. |
queryable_fields_names string[] | A list of field names to use as global queryable fields. |
indexed_queryable_fields_names string[] | A list of field names to use as the indexed queryable field. While this property is an array, Sync currently supports only one one indexed queryable field. Therefore, this array may contain at most one element. The indexed queryable field must be present in the schema and be
the same eligible field type in every collection you
sync. The indexed queryable field name must also appear in
|
collection_queryable_fields_names { [collectionName: string]: string[] } | A map from collection names to a list of collection-level
queryable fields for each collection. |
last_disabled number | The date and time that sync was last paused or disabled, represented by
the number of seconds since the Unix epoch (January 1, 1970, 00:00:00
UTC). |
asymmetric_tables string[] | An array of the names of collections that are defined as asymmetric
with Data Ingest, where clients can write
data but not read. |