Sync Changes Between Devices - .NET SDK

On this page

Before you can access a synced realm from the client, you must:

To open a synced realm, call the GetInstanceAsync() method, passing in a SyncConfiguration object that includes the partition name and the user. The following code demonstrates this:

config = new SyncConfiguration("myPart", user);
var realm = await Realm.GetInstanceAsync(config);

In the above example, the code shows how to open the realm asynchronously by calling GetInstanceAsync(). You can also open a realm synchronously by calling the GetInstance() method, which is necessary if the device is offline.

var synchronousRealm = Realm.GetInstance(config);

The first time a user logs on to your realm app, you should open the realm asynchronously to sync data from the server to the device. After that initial connection, you can open a realm synchronously to ensure the app works in an offline state.

The partition value specifies which subset of your data to sync. This is typically a user ID, project ID, store ID, or some other category identifier in your app that has particular relevance to the current user.

See also:

The syntax to read and write on a synced realm is identical to the syntax for non-synced realms. While you work with local data, a background thread efficiently integrates, uploads, and downloads changesets.

When Using Sync, Avoid Writes on the Main Thread

The fact that Realm performs sync integrations on a background thread means that if you write to your realm on the main thread, there's a small chance your UI could appear to hang as it waits for the background sync thread to finish a write transaction. Therefore, it's a best practice never to write on the main thread when using Realm Sync.

The following code creates a new Task object and writes it to the realm:

var testTask = new Task
Name = "Do this thing",
Status = TaskStatus.Open.ToString(),
Partition = "myPart"
realm.Write(() =>
See also:

Opening a synced realm starts a Sync Session. To pause synchronization for a specific session, you can call the Stop() method on the session.

When you then call the Start() method on the paused session, the Sync session resumes.

Each session is independent

You must manually call the Stop() and Start() methods for each realm whose Sync session you want to pause and restart. The sync state of one session has no impact on other open sessions.

The following code block demonstrates calling the Stop() and Start() methods:

var session = realm.GetSession();

You can check on the status of your current changes by waiting for changes to be uploaded or downloaded or by displaying a progress bar.

To asynchronously wait for your changes to be completed, get the sync session by calling Realms.Sync.GetSession(). Then call session.WaitForUploadAsync() or session.WaitForDownloadAsync().

using Realms.Sync;
var realm = Realm.GetInstance(config);
await realm.GetSession().WaitForDownloadAsync();

You can use progress notifications to display a progress bar. First, get the sync session by calling Realms.Sync.GetSession(). Then, add a progress notification using the session.GetProgressObservable() method.

The session.GetProgressObservable method takes in the following two parameters:

  • A ProgressDirection parameter that can be set to ProgressDirection.Upload or ProgressDirection.Download to register notifications for either event.
  • A ProgressMode parameter that can be set to ProgressMode.ReportIndefinitely for the notifications to continue until the callback is unregistered, or ProgressMode.ForCurrentlyOutstandingWork for the notifications to continue until only the currently transferable bytes are synced.

In the following example, an application developer registers a progress observable on the session to listen for upload events indefinitely. When this callback is triggered, the console prints the number of transferred bytes and the number of transferable bytes.


The following snippet requires the System.Reactive NuGet package.

var session = realm.GetSession();
var token = session.GetProgressObservable(ProgressDirection.Upload, ProgressMode.ReportIndefinitely)
.Subscribe(progress =>
Console.WriteLine($"transferred bytes: {progress.TransferredBytes}");
Console.WriteLine($"transferable bytes: {progress.TransferableBytes}");

Once you no longer wish to receive notifications, unregister the token by using token.Dispose()


The number of transferred and transferable bytes are estimates. Since the actual changesets are compressed through gzip before transmitting over the network, the actual transmitted sizes will be much smaller for both transferable and transferred bytes.


Realm will try to optimize download speeds by combining multiple changesets into a single download message up to 16 MB. Since the progress callback is only invoked once before and after a download message is processed, this means that you'll likely see transferredBytes change in increments of roughly 16 MB rather than continuously as the message is being downloaded."

Realm Sync represents errors via SessionExceptions. In addition to the standard exception properties, you have access to an ErrorCode that contains information about the type of the error and allows you to have strongly typed handling logic.

Session.Error += (session, errorArgs) =>
var sessionException = (SessionException)errorArgs.Exception;
switch (sessionException.ErrorCode)
case ErrorCode.AccessTokenExpired:
case ErrorCode.BadUserAuthentication:
// Ask user for credentials
case ErrorCode.PermissionDenied:
// Tell the user they don't have permissions to work with that Realm
case ErrorCode.Unknown:
// Likely the app version is too old, prompt for update
// ...

To control which messages are logged by the sync client logger, set the LogLevel property of the AppConfiguration object:

var appConfig = new AppConfiguration(myRealmAppId)
LogLevel = LogLevel.Debug,

To diagnose and troubleshoot errors while developing your application, set the log level to debug or trace. For production deployments, decrease the log level for improved performance.

To set a custom logger function, set Logger.Default to a custom Logger function.

using Realms.Logging;
Logger.LogLevel = LogLevel.All;
// customize the logging function:
Logger.Default = Logger.Function(message =>
// Do something with the message
Give Feedback

On this page