Docs Menu
Docs Home
/ /
Atlas Device SDKs
/

Partition-Based Sync

On this page

  • Migrate from Partition-Based Sync to Flexible Sync
  • Update Client Code After Migration
  • Open a Synced Database with Partition-Based Sync

Partition-Based Sync is a legacy mode for using Atlas Device Sync with Atlas Device SDK. You can no longer create new Partition-Based Sync apps. All of the Device Sync-related content on other pages in the SDK docs assume your app uses the default Sync mode, Flexible Sync.

This page covers how to migrate a Partition-Based Sync app to a Flexible Sync app. For apps that still use Partition-Based Sync, this page also has details for opening a database with Partition-Based Sync.

Tip

C++ and Flutter SDKs Do Not Support Partition-Based Sync

The examples on this page do not include details for C++ or Dart because the C++ and Flutter SDKs have never supported Partition-Based Sync.

You can migrate your app from Partition-Based Sync mode to Flexible Sync. Migrating is an automatic process that does not require any changes to your application code. Automatic migration requires the following minimum SDK versions:

  • .NET SDK v11.1.0 and later

  • Java SDK v10.16.0 and later

  • Kotlin SDK v1.9.0 and later

  • Node.js SDK v11.10.0 and later

  • Swift SDK v10.40.0 and later

Migrating enables you to keep your existing App Services users and authentication configuration. Flexible Sync provides more versatile permissions configuration options and more granular data synchronization.

For more information about how to migrate your App Services App from Partition-Based Sync to Flexible Sync mode, refer to Migrate Device Sync Modes in the App Services documentation.

The automatic migration from Partition-Based Sync to Flexible Sync does not require any changes to your client code. However, to support this functionality, the SDK automatically handles the differences between the two Sync Modes by:

  • Automatically creating Sync subscriptions for each object type where partitionKey == partitionValue.

  • Injecting a partitionKey field into every object if one does not already exist. This is required for the automatic Sync subscription.

If you need to make updates to your client code after migration, consider updating your client codebase to remove this hidden migration functionality.

You might want update your client codebase when:

  • You add a new model or change a model in your client codebase.

  • You add or change functionality that involves reading or writing SDK objects.

  • You want to implement more fine-grained control over what data you sync.

Make these changes to convert your Partition-Based Sync client code to use Flexible Sync:

1

Change your PartitionSyncConfiguration to a FlexibleSyncConfiguration.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

1

Update your SyncConfiguration.Builder to use Flexible Sync. This involves removing the partitionValue and adding a set of initial subscriptions, if needed.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

Remove automatic Flexible Sync subscriptions. If you did not add initial subscriptions in the SyncConfiguration.Builder, manually create the relevant subscriptions.

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

1

Add flexible:true to your SyncConfiguration object where you open a synced database.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

1

Update your SyncConfiguration.Builder() to use Flexible Sync where you open a synced database. This involves removing the partitionValue and adding a set of initial subscriptions, if needed.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

1

Update your SyncConfiguration.Builder to use Flexible Sync. This involves removing the partitionValue and adding a set of initial subscriptions, if needed.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

Remove automatic Flexible Sync subscriptions. If you did not add initial subscriptions in the SyncConfiguration.Builder, manually create the relevant subscriptions.

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

1

Switch to a RLMUser -flexibleSyncConfiguration where you open a synced database.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

1

Switch to a flexibleSyncConfiguration() where you open a synced database.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

1

Add flexible:true to your SyncConfiguration object where you open a synced database.

2

Add relevant properties to your object models to use in your Flexible Sync subscriptions. For example, you might add an ownerId property to enable a user to sync only their own data.

3

When you migrate from Partition-Based Sync to Flexible Sync, the SDK automatically creates hidden Sync subscriptions for your app. The next time you add or change subscriptions, we recommend that you:

  1. Remove the automatically-generated subscriptions.

  2. Manually add the relevant subscriptions in your client codebase.

This enables you to see all of your subscription logic together in your codebase for future iteration and debugging.

For more information about the automatically-generated Sync subscriptions, refer to Migrate Client App to Flexible Sync.

For examples of Flexible Sync permissions strategies, including examples of how to model data for these strategies, refer to the Device Sync Permissions Guide in the App Services documentation.

You can open a synced database for Partition-Based Sync by passing the appropriate partition value in the Sync configuration.

Tip

Partition Value

For App Services Apps that use Partition-Based Sync, your client implementation must include a partition value. This is the value of the partition key field in the Partition-Based Sync configuration.

The partition value determines which data the client application can access.

You pass in the partition value when you open a synced database.

  1. Create a PartitionSyncConfiguration object that includes the partition value and the User object.

  2. Open a synced database asynchronously by calling the GetInstanceAsync() method, or synchronously with the GetInstance() method. Pass in the PartitionSyncConfiguration object.

The following code demonstrates these steps:

To configure settings for a database, create a SyncConfiguration with a SyncConfiguration.Builder.

The following example configures a synced database with:

  • Partition-Based Sync

  • Synchronous reads explicitly allowed on the UI thread

  • Synchronous writes explicitly allowed on the UI thread

  • Explicit waiting for all backend changes to synchronize to the device before returning an open database

  • Automatic compaction when launching the database to save file space

Important

Synchronous Reads and Writes on the UI Thread

By default, you can only read or write to a database in your application's UI thread using asynchronous transactions. That is, you can only use Realm methods whose name ends with the word Async in the main thread of your Android application unless you explicitly allow the use of synchronous methods.

This restriction exists for the benefit of your application users: performing read and write operations on the UI thread can lead to unresponsive or slow UI interactions, so it's usually best to handle these operations either asynchronously or in a background thread. However, if your application requires the use of synchronous database reads or writes on the UI thread, you can explicitly allow the use of synchronous methods with the following SyncConfiguration options:

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
);
}
});

To open a database with Partition-Based Sync, call Realm.open(). Pass in a Configuration object, which must include the sync property defining a SyncConfiguration object. In the SyncConfiguration, you must include include user and partitionValue.

To open a Partition-Based Sync database, pass a user, a partition, and a set of SDK object schemas to SyncConfiguration.Builder(). Then, pass the configuration to Realm.open() to open an instance of the database:

To configure settings for a database, create a SyncConfiguration with a SyncConfiguration.Builder.

The following example configures a synced database with:

  • Partition-Based Sync

  • Synchronous reads explicitly allowed on the UI thread

  • Synchronous writes explicitly allowed on the UI thread

  • Explicit waiting for all backend changes to synchronize to the device before returning an open database

  • Automatic compaction when launching the database to save file space

Important

Synchronous Reads and Writes on the UI Thread

By default, you can only read or write to a database in your application's UI thread using asynchronous transactions. That is, you can only use Realm methods whose name ends with the word Async in the main thread of your Android application unless you explicitly allow the use of synchronous methods.

This restriction exists for the benefit of your application users: performing read and write operations on the UI thread can lead to unresponsive or slow UI interactions, so it's usually best to handle these operations either asynchronously or in a background thread. However, if your application requires the use of synchronous database reads or writes on the UI thread, you can explicitly allow the use of synchronous methods with the following SyncConfiguration options:

val config = SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm with reads and writes allowed on the UI thread.")
}
})

The first time you log in and open a synced database, log in the user, and pass the user's RLMSyncConfiguration object with the desired partitionValue to +[RLMRealm realmWithConfiguration:error:].

This opens a synced database on the device. The database attempts to sync with your App in the background to check for changes on the server, or upload changes that the user has made.

Pass a logged-in user's configuration object with the desired partition value to realm initializers.

You can optionally specify whether a database should download changes before opening. If you do not specify download behavior, this opens a database with data that is on the device, and attempts to sync changes in the background.

To open a database with Partition-Based Sync, call Realm.open(). Pass in a Configuration object, which must include the sync property defining a SyncConfiguration object. In the SyncConfiguration, you must include include user and partitionValue.

user = await app.LogInAsync(
Credentials.EmailPassword("caleb@mongodb.com", "MySekritPwd"));
config = new PartitionSyncConfiguration("myPart", user);
try
{
realm = await Realm.GetInstanceAsync(config);
}
catch (Exception ex)
{
Console.WriteLine($@"Error creating or opening the
realm file. {ex.Message}");
}
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.waitForInitialRemoteData(500, TimeUnit.MILLISECONDS)
.compactOnLaunch()
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
}
});
const config = {
schema: [Car],
sync: {
user: app.currentUser,
partitionValue: "myPartition",
},
};
const realm = await Realm.open(config);
val app = App.create(YOUR_APP_ID)
runBlocking {
val user = app.login(Credentials.anonymous())
val config =
SyncConfiguration.Builder(user, PARTITION, setOf(/*realm object models here*/))
// specify name so realm doesn't just use the "default.realm" file for this user
.name(PARTITION)
.build()
val realm = Realm.open(config)
Log.v("Successfully opened realm: ${realm.configuration.name}")
realm.close()
}
val config =
SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.waitForInitialRemoteData(500, TimeUnit.MILLISECONDS)
.compactOnLaunch()
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
}
})
RLMApp *app = [RLMApp appWithId:YOUR_APP_ID];
// Log in...
RLMUser *user = [app currentUser];
NSString *partitionValue = @"some partition value";
RLMRealmConfiguration *configuration = [user configurationWithPartitionValue:partitionValue];
NSError *error = nil;
RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration
error:&error];
if (error != nil) {
NSLog(@"Failed to open realm: %@", [error localizedDescription]);
// handle error
} else {
NSLog(@"Opened realm: %@", realm);
// Use realm
}
let app = App(id: YOUR_APP_SERVICES_APP_ID)
// Store a configuration that consists of the current user,
// authenticated to this instance of your app. If there is no
// user, your code should log one in.
let user = app.currentUser
let partitionValue = "some partition value"
var configuration = user!.configuration(partitionValue: partitionValue)
// Open the database with the user's configuration.
let syncedRealm = try! Realm(configuration: configuration)
print("Successfully opened the synced realm: \(syncedRealm)")
const config: Realm.Configuration = {
schema: [Car],
sync: {
user: app.currentUser!,
partitionValue: "myPartition",
},
};
const realm = await Realm.open(config);

Back

Stream Data to Atlas

Next

Event Library - Swift SDK Only