Docs Menu
Docs Home
/ /
Atlas Device SDKs
/

Manage Sync Subscriptions

On this page

  • What are Subscriptions?
  • Subscribe to Object Types
  • Permissions
  • Manage Subscriptions in Your Client App
  • Initial Subscriptions
  • Subscribe to Queries
  • Subscribe to a Query
  • Subscribe to a Query with a Subscription Name
  • Wait for a Query Subscription to Sync
  • Unsubscribe from a Query
  • Manually Manage Subscriptions
  • Access the Subscription Set
  • Find a Subscription
  • Add a Subscription
  • Wait for Subscription Changes to Sync
  • Check Subscription Set State
  • Change Subscription Queries
  • Remove Subscriptions
  • Performance Considerations
  • API Efficiency
  • Group Updates for Improved Performance
  • Sync RQL Requirements and Limitations
  • Indexed Queryable Fields Subscription Requirements
  • Unsupported Sync Subscription Query Operators
  • List Queries
  • Embedded or Linked Objects

Atlas Device Sync uses subscriptions and permissions to determine what data to sync with your client application.

After you open a synced database, you must add subscriptions before you can read to and write from the database.

You can manually add, update, and remove subscriptions to determine which data syncs to the client device. Or you can subscribe to queries instead of or in addition to manually managing subscriptions.

When you configure Device Sync in Atlas, you specify which fields your client application can query. The SDK tracks these queries through a subscription. When you subscribe to a query, the SDK automatically tracks changes to data matching that subscription, and uploads and downloads relevant data.

Each subscription corresponds to a query on queryable fields for a specific object type. See Queryable Fields in the Device Sync documentation for more information.

For each query subscription, the SDK looks for data matching the query. Data matching the subscription, where the user has the appropriate permissions, syncs between clients and the backend application.

The SDK tracks these queries through a subscription set, which is a collection of subscriptions. You can add, remove, and update subscriptions in the subscription set.

You can construct subscription queries with Realm Query Language (RQL), or one of the SDK-idiomatic query engines.

Important

RQL Support in Sync Subscription Queries

Device Sync does not support the full range of RQL operators when constructing a subscription query. For details about these limitations, refer to Sync RQL Requirements and Limitations.

Subscription sets are based on your data model object types. You might have multiple subscriptions if you have many types of SDK objects. You can also have multiple subscriptions on the same object type.

However, note the following if you use relationships or asymmetric objects in your app:

You must add both an object and its linked object to the subscription set to see a linked object.

If your subscription results contain an object with a property that links to an object not contained in the results, the link appears to be nil. The SDK does not provide a way to distinguish whether that property's value is legitimately nil, or whether the object it links to exists but is out of view of the query subscription.

If your app uses Data Ingest to unidirectionally sync asymmetric objects, you cannot create subscriptions for those objects. If your app contains asymmetric objects and non-asymmetric objects in the same database, you can add subscription queries for the non-asymmetric objects.

Subscriptions work hand-in-hand with permissions to determine what data to Sync to your client application. The client application only sees the subset of data that matches your subscriptions which also matches the permissions of the logged-in user. For more information about the intersection of subscriptions and user permissions, refer to Write Data to a Synced Database.

This page details how to manage client subscriptions for Device Sync. For information about setting up permissions for Device Sync, see: Device Sync Rules & Permissions.

In the client application, you add, update, and remove subscriptions to specific queries on the queryable fields. This determines which data syncs to the client device.

You can:

  • Add subscriptions with an optional subscription name:

    • You can subscribe to a database query. This automatically adds the subscription to the subscription set.

    • Manually add a subscription to the subscription set with the subscribe API. Use this API if you need more control over subscriptions for performance optimization or business-logic reasons. See Performance Considerations for more information.

  • React to subscription state changes.

  • Update subscriptions with new queries.

  • Remove individual subscriptions or all subscriptions for an object type.

Subscriptions persist across user sessions unless you unsubscribe from them.

Before you can read from or write to a synced database, you must provide at least one subscription. Some of the SDK languages provide a dedicated API to make it more convenient to set initial subscriptions. For details, refer to Set Initial Subscriptions.

To simplify subscription management, the SDK offers APIs to subscribe to and unsubscribe from a query directly. These APIs abstract away the details of manually adding and removing subscriptions. This API is not available for all languages. If your preferred language does not provide this API, refer to Manually Manage Subscriptions.

Important

The Subscribe to Queries API is in Preview

The APIs described here are currently in Preview. These APIs may be subject to change in the future.

With an authenticated user and a Sync configuration, you can open a synced database and query for the objects you want to read and write. You can subscribe to the query to create a subscription for objects matching the query.

This creates an unnamed subscription and adds it to the subscription set, similar to manually creating a subscription.

Subscriptions persist across user sessions unless you unsubscribe from them.

Tip

If your app works with multiple subscriptions, or if you want to update a subscription, you should add a name when you subscribe to a query. For details, refer to the Subscribe to a Query with a Subscription Name section on this page.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

To subscribe to a query, pass the following arguments to subscribe():

  • RealmResults query: Required. A RealmResults object that you can create using the Realm Query Language.

  • String name: Optional. Name for the subscription that you can refer to.

  • bool update: Optional. When true, adding a subscription with an existing name replaces the existing query with the new query. When false, the SDK throws an exception for duplicate subscriptions. Only use with named subscriptions.

In the following example, we subscribe to two new named queries.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

To subscribe to a query:

  1. Query for the objects that you want to read and write.

  2. Call subscribe() on the query results to create a sync subscription for objects matching the query.

  3. Pass a SubscriptionOptions object.

Most of the time, you should give your subscriptions a name. If you don't, the name is set to null.

If you use filtered() on an unnamed query subscription, the subscription identifier is based on the filtered query. This means that every time your query string changes, subscribe() will create a new subscription.

To subscribe to a RealmQuery or RealmResults set, call the .subscribe() method.

// Subscribe to a specific query
val realmResults = realm.query<Task>("progressMinutes >= $0", 60)
.subscribe()
// Subscribe to all objects of a specific type
val realmQuery = realm.query<Team>()
realmQuery.subscribe()

You can update a named query subscription with a new query by setting updateExisting to true.

This updates the subscription automatically, instead of requiring you to manually update the subscription in the subscription set.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

Use the .subscribe() method to create a subscription for objects matching the query.

let realm = try await Realm(configuration: flexSyncConfig)
let results = try await realm.objects(Task.self)
.where { $0.progressMinutes >= 60 }.subscribe()
// Go on to work with subscribed results

You can subscribe to actor-confined queries. For more information about working with actor-confined database instances, refer to Use Atlas Device SDK for Swift with Actors.

You can subscribe to an actor-confined query on the MainActor.

let realm = try await Realm(configuration: flexSyncConfig, actor: MainActor.shared)
let results = try await realm.objects(Team.self)
.where { $0.teamName == "Developer Education" }
.subscribe(name: "team_developer_education")
// Go on to work with subscribed results

Or subscribe to a query on a custom actor.

To subscribe to a query:

  1. Query for the objects that you want to read and write.

  2. Call subscribe() on the query results to create a sync subscription for objects matching the query.

  3. Pass a SubscriptionOptions object.

Most of the time, you should give your subscriptions a name. If you don't, the name is set to null.

If you use filtered() on an unnamed query subscription, the subscription identifier is based on the filtered query. This means that every time your query string changes, subscribe() will create a new subscription.

// The C++ SDK does not currently support this API.
// The .NET SDK does not currently support this API.
final boatQuery = realm.all<Boat>();
final bigPlaneQuery = realm.query<Plane>("numSeats > 100");
final boatSubscription = await boatQuery.subscribe(name: "boats");
final planeSubscription =
await bigPlaneQuery.subscribe(name: "big-planes");
// The Java SDK does not support this API.
const config = {
schema: [Task],
sync: {
user: app.currentUser,
flexible: true,
},
};
const realm = await Realm.open(config);
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe();
// ...work with the subscribed results list
// Create a subscription named "bob_smith_teams"
val results = realm.query<Team>("$0 IN members", "Bob Smith")
.subscribe("bob_smith_teams")
// Add another subscription with the same name with `updateExisting` set to true
// to replace the existing subscription
val updateResults =
realm.query<Team>("$0 IN members AND teamName == $1", "Bob Smith", "QA")
.subscribe("bob_smith_teams", updateExisting = true)
// The Java SDK does not support this API.
let realm = try await Realm(configuration: flexSyncConfig, actor: CustomGlobalActor.shared)
let results = try await realm.objects(Team.self)
.where { $0.teamName == "Developer Education" }
.subscribe(name: "team_developer_education")
// Go on to work with subscribed results
const config: Realm.Configuration = {
schema: [Task],
sync: {
user: app.currentUser!,
flexible: true,
},
};
const realm = await Realm.open(config);
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe();
// ...work with the subscribed results list

If your app works with multiple subscriptions, or if you want to update a subscription, you should add a name when you subscribe to a query.

You can later use this name to:

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

To subscribe to a query with a name, pass the following arguments to subscribe():

  • RealmResults query: Required. A RealmResults object that you can create using the Realm Query Language.

  • String name: Optional. Name for the subscription that you can refer to.

In the following example, we subscribe to two new named queries.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

To subscribe to a query:

  1. Query for the objects that you want to read and write.

  2. Call subscribe() on the query results to create a sync subscription for objects matching the query.

  3. Pass a SubscriptionOptions object that contains the name property to subscribe().

To add a name to the subscription, pass a string when you call .subscribe().

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

To give a query subscription a name, supply a string name argument for the name parameter when you call the .subscribe() method.

To subscribe to a query:

  1. Query for the objects that you want to read and write.

  2. Call subscribe() on the query results to create a sync subscription for objects matching the query.

  3. Pass a SubscriptionOptions object that contains the name property to subscribe().

// The C++ SDK does not currently support this API.
// The .NET SDK does not currently support this API.
final boatQuery = realm.all<Boat>();
final bigPlaneQuery = realm.query<Plane>("numSeats > 100");
final boatSubscription = await boatQuery.subscribe(name: "boats");
final planeSubscription =
await bigPlaneQuery.subscribe(name: "big-planes");
// The Java SDK does not support this API.
const subOptions = {
name: "All completed tasks",
};
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe(subOptions);
const completedTasksSubscription = realm.subscriptions.findByName(
"All completed tasks"
);
// ...work with the subscribed results list or modify the subscription
// Add a subscription named "team_developer_education"
val results = realm.query<Team>("teamName == $0", "Developer Education")
.subscribe("team_developer_education")
// The Java SDK does not support this API.
let realm = try await Realm(configuration: flexSyncConfig)
let results = try await realm.objects(Team.self)
.where { $0.teamName == "Developer Education" }
.subscribe(name: "team_developer_education")
// Go on to work with subscribed results
const completedTasks = await realm
.objects(Task)
.filtered('status == "completed"')
.subscribe({ name: "All completed tasks" });
const completedTasksSubscription = realm.subscriptions.findByName(
"All completed tasks"
);
// ...work with the subscribed results list or modify the subscription

When you subscribe to a query, that query's results do not contain objects until the subscription syncs with Atlas.

If your app creates objects, you may not need to download synced data before the user works with it. However, if your app requires data from Atlas before the user can work with your app, you can specify that the SDK should wait for the subscription query data to sync before proceeding.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

When you do need specify the desired sync behavior, configure the waitForSyncMode option.

This example uses the firstTime option, which is the default behavior. A subscription with firstTime behavior only waits for sync to finish when a subscription is first created.

final bigPlaneQuery = realm.query<Plane>("numSeats > 100");
final planeSubscription = await bigPlaneQuery.subscribe(
name: "firstTimeSync",
waitForSyncMode: WaitForSyncMode.firstTime,
);

The other supported waitForSyncMode options are:

  • always: Wait to download matching objects every time your app launches. The app must have an internet connection at every launch.

  • never: Never wait to download matching objects. The app needs an internet connection for the user to authenticate the first time the app launches, but can open offline on subsequent launches using cached credentials.

You can optionally specify a cancellationToken to limit how long the sync download runs.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

When you call the .subscribe() method on a query, you can optionally specify the WaitForSync behavior, which is an enum of options describing different sync behaviors.

The supported WaitForSync options are:

  • FirstTime: Wait for sync to finish when a subscription is first created.

  • Always: Wait to download matching objects every time your app launches. The app must have an internet connection at every launch.

  • Never: Never wait to download matching objects. The app needs an internet connection for the user to authenticate the first time the app launches, but can open offline on subsequent launches using cached credentials.

You can optionally specify a timeout value to limit how long the sync download runs.

To add a name to the subscription, pass a string when you call .subscribe().

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

To wait for a query subscription to sync, pass the waitForSync parameter when you call the .subscribe() method. This takes a WaitForSyncMode enum argument, whose cases are:

  • .onCreation: Wait to download matching objects when your app creates the subscription. Otherwise, return without waiting for new downloads. The app must have an internet connection the first time you add the subscription.

  • .always: Wait to download matching objects when .subscribe() is executed. The app must have an internet connection when .subscribe() is executed.

  • .never: Never wait to download matching objects. The app needs an internet connection for the user to authenticate the first time the app launches, but can open offline on subsequent launches using cached credentials.

You can optionally specify a timeout value of type TimeInterval.

When you call the .subscribe() method on a query, you can optionally specify the WaitForSync behavior, which is an enum of options describing different sync behaviors.

This example uses the FirstTime option, which is the default behavior. A subscription with FirstTime behavior only waits for sync to finish when a subscription is first created.

import { WaitForSync } from "realm";
// Get tasks that have a status of "in progress".
const completedTasks = realm
.objects(Task)
.filtered("status == 'completed'");
// Only waits for sync to finish on the initial sync.
await completedTasks.subscribe({
behavior: WaitForSync.FirstTime,
name: "First time sync only",
});

The other supported WaitForSync options are:

  • Always: Wait to download matching objects every time your app launches. The app must have an internet connection at every launch.

  • Never: Never wait to download matching objects. The app needs an internet connection for the user to authenticate the first time the app launches, but can open offline on subsequent launches using cached credentials.

You can optionally specify a timeout value to limit how long the sync download runs.

// The C++ SDK does not currently support this API.
// The .NET SDK does not currently support this API.
final bigPlaneQuery = realm.query<Plane>("numSeats > 200");
final planeSubscription = await bigPlaneQuery.subscribe(
name: "alwaysWaitSync",
waitForSyncMode: WaitForSyncMode.always,
cancellationToken: TimeoutCancellationToken(Duration(seconds: 5)),
);
// The Java SDK does not support this API.
// The documentation does not currently have this code example in JavaScript.
// Please refer to the other languages or related pages for example code.
// Subscribe to a specific query
val realmResults = realm.query<Task>("progressMinutes >= $0", 60)
.subscribe()
// Subscribe to all objects of a specific type
val realmQuery = realm.query<Team>()
realmQuery.subscribe()
// The Java SDK does not support this API.
let realm = try await Realm(configuration: flexSyncConfig)
let results = try await realm.objects(Team.self)
.where { $0.members.contains("Bob Smith") }
.subscribe(
name: "bob_smith_teams",
waitForSync: .onCreation)
// After waiting for sync, the results set contains all the objects
// that match the query - in our case, 1
print("The number of teams that have Bob Smith as a member is \(results.count)")
import { WaitForSync } from "realm";
// Get tasks that have a status of "in progress".
const completedTasks = realm
.objects(Task)
.filtered("status == 'completed'");
// Add subscription with timeout
// If timeout expires before sync is completed, currently-downloaded
// objects are returned and sync download continues in the background.
const taskSubscription = await completedTasks.subscribe({
behavior: WaitForSync.Always,
timeout: 500,
});

You can unsubscribe from a query that you have previously subscribed to. Unsubscribing removes the suscription from the subscription set, similar to manually removing a subscription.

A query results set may still contain objects after calling the unsubscribe method if the subscription set contains another overlapping subscription.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

You can unsubscribe from a query's results using unsubscribe().

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

To unsubscribe from a query's results, call the unsubscribe() method.

Kotlin does not currently support the unsubscribe API. Instead, you can manually remove subscriptions from the subscription set.

The selected language does not support the API that enables you to subscribe to a query. Instead, refer to manually manage queries.

You can unsubscribe from a query's Results set by calling .unsubscribe() on the query. This removes the subscription from the MutableSubscriptionSet.

To unsubscribe from a query's results, call the unsubscribe() method.

// The C++ SDK does not currently support this API.
// The .NET SDK does not currently support this API.
planeQuery.unsubscribe();
trainQuery.unsubscribe();
// The Java SDK does not support this API.
// The documentation does not currently have this code example in JavaScript.
// Please refer to the other languages or related pages for example code.
// The Kotlin SDK does not currently support this API.
// The Java SDK does not support this API.
let realm = try await Realm(configuration: flexSyncConfig)
let results = try await realm.objects(Task.self).where { $0.completed == false }.subscribe()
// Go on to work with subscribed results.
// Later...
results.unsubscribe()
import { WaitForSync } from "realm";
// Get tasks that have a status of "in progress".
const completedTasks = realm
.objects(Task)
.filtered("status == 'completed'");
// Only waits for sync to finish on the initial sync.
await completedTasks.subscribe({
behavior: WaitForSync.FirstTime,
name: "First time sync only",
});
// Unsubscribe
completedTasks.unsubscribe();

The unsubscribe method returns before objects matching the removed subscription are deleted from the database. Sync continues in the background based on the new set of subscriptions. There is no API to wait for the unsubscribe method to sync with the server.

As an alternative to the subscribe to a query API, you can manually manage the subscriptions in a subscription set.

You can:

  • Add subscriptions

  • React to subscription state change

  • Update subscriptions with new queries

  • Remove individual subscriptions or all subscriptions for an object type

Data matching the subscription, where the user has the appropriate permissions, syncs between devices and Atlas.

You can specify an optional string name for your subscription.

When you create a subscription, the SDK looks for data matching a query on a specific object type. You can have multiple subscription sets on different object types. You can also have multiple queries on the same object type.

You can access the subscription set through the database subscriptions property. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

You can access the subscription set through the subscriptions() public member function of a realm. This provides the sync_subscription_set where you can use the size(), find(), or update() member functions. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

You can access the SubscriptionSet through the database Subscriptions property. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

you can access a SubscriptionSet, a collection of subscriptions, through the Realm.subscriptions property. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

You can access the SubscriptionSet through the Realm.getSubscriptions() method. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

When using a synced database, you can access a SubscriptionSet, a collection of subscriptions, through the realm.subscriptions property. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

You can access a SubscriptionSet through the database subscriptions property. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

You can access the SubscriptionSet through the Realm.getSubscriptions() method. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

You can access a SyncSubscriptionSet through the database subscriptions property. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

When using a synced database, you can access a SubscriptionSet, a collection of subscriptions, through the realm.subscriptions property. You perform all operations to add, find, update, remove, or watch subscriptions through this property.

// The documentation does not currently have this code example in C++.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in C#.
// Please refer to the other languages or related pages for example code.
final subscriptions = realm.subscriptions;
// The documentation does not have this code example in Java.
// Please refer to the other languages or related pages for example code.
// get the SubscriptionSet for the realm
const subscriptions = realm.subscriptions;
// The documentation does not currently have this code example in Kotlin.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Kotlin for the Java SDK.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Swift.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

You can find a specific subscription in a subscription set. You might want to find a specific subscription:

  • To avoid adding the same subscription again, which in some languages throws an error.

  • To update the subscription.

  • To remove the subscription.

To find a specific subscription, call the subscriptions().find() method with the name of a subscription.

You cannot find unnamed subscriptions in C++.

To find a specific subscription by name, call the Find() method with the name of a subscription.

You can also find a subscription matching a specific query by calling the Find() method with an IQueryable<T> argument.

To find a specific subscription by name, call the findByName() method with the name of a subscription.

You can also find a subscription matching a specific query by calling the find() method with an RQL query.

To find a specific subscription by name, call the find() method with the name of a subscription.

You can also find a subscription matching a specific query by calling the find() method with a RealmQuery argument.

To find a specific subscription by name, call the findByName() method with the name of a subscription.

You can also find a subscription matching a specific query by calling the findByQuery() method with a query to match against.

To find a specific subscription by name, call the findByName() method with the name of a subscription.

You can also find a subscription matching a specific query by calling the findByQuery() method with a RealmQuery argument.

To find a specific subscription by name, call the find() method with the name of a subscription.

You can also find a subscription matching a specific query by calling the find() method with a RealmQuery argument.

To find a specific subscription by name, call the subscriptions.first(named: ) method with the name of a subscription.

You can also find a subscription matching a specific query by calling one of the variants of subscriptions.first(ofType: where:) method with the SDK object type and a query, query builder, or NSPredicate argument.

To find a specific subscription by name, call the findByName() method with the name of a subscription.

You can also find a subscription matching a specific query by calling the findByQuery() method with a query to match against.

// Check the subscription count
CHECK(syncedRealm.subscriptions().size() == 1);
// Find a specific subscription by name
auto puppySubscription = *syncedRealm.subscriptions().find("puppies");
CHECK(puppySubscription.name == "puppies");
// Get information about the subscription
CHECK(puppySubscription.object_class_name == "Dog");
CHECK(puppySubscription.query_string == "age < 3");
// The documentation does not currently have this code example in C#.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Dart.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Java.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in JavaScript.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Kotlin.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Kotlin for the Java SDK.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Swift.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

Add a subscription in a subscriptions update block. You append each new subscription to the client's SDK subscriptions.

Subscriptions persist across user sessions unless you remove them from the subscription set.

If your app is adding subscriptions for the first time, some SDK languages provide a special parameter to set initial subscriptions or recalculate initial subscriptions on app launch. For details, skip to the set initial subscriptions on this page.

Tip

If your app works with multiple subscriptions, or if you want to update a subscription, you should add a name when you subscribe to a query. For details, refer to the Add a Named Subscription section on this page.

To add a subscription:

  1. Open the synced database.

  2. Access the database's subscriptions property.

  3. Open a subscription update block.

  4. Call the add method with the object type to append the new subscription to the subscription set. Optionally, add a query to subscribe to only a subset of the objects that match the query.

Note

The C++ SDK does not yet support the full range of query expressions that the other SDKs provide.

To add a subscription:

  1. Open the synced database.

  2. Access the database's Realm.Subscriptions property.

  3. Open a subscription Update block.

  4. Create a subscription to a specific object type. Optionally add a query to subscribe to only a subset of the objects that match the query.

  5. Call the Subscriptions.Add method with the subscription you just created to append the new subscription to the subscription set.

Alternately, to add a subscription to an existing subscription set, create the query and then call IQueryable.SubscribeAsync().

The SubscribeAsync method is shorthand for using SubscriptionSet.Update() to create an update block, and then calling the SubscriptionSet.Add() method on the SubscriptionSet.

To add a subscription:

  1. Open the synced database.

  2. Access the database's subscriptions property to interact with the SubscriptionSet.

  3. Open a subscription update block by calling SubscriptionSet.update().

  4. Call the add method to append the new subscription to the subscription set.

  5. Pass a RealmResults query that you can create using the Realm Query Language query. Optionally, add a query name.

To add a subscription:

  1. Open the synced database.

  2. Call the getSubscriptions() method to interact with the subscription set.

  3. Open a subscription update block using SubscriptionSet.update().

  4. Use the MutableSubscriptionSet.addOrUpdate() method to append the new subscription to the subscription set.

  5. Call Subscription.create() with a query to a specific object type. Optionally, add a name for the query.

To add a subscription:

  1. Open the synced database.

  2. Access the database's realm.subscriptions property.

  3. Open a subscription update block.

  4. Create a subscription to a specific object type. Optionally add a query to subscribe to only a subset of the objects that match the query.

  5. Call the add() method with the subscription you just created to append the new subscription to the subscription set. Optionally, you can name the subscription.

To add a subscription:

  1. Open the synced database.

  2. Access the database's subscriptions property.

  3. Open a subscription update block.

  4. Call the add method to append the new subscription to the subscription set.

  5. Pass a query with the name of the object type. Optionally, use Realm Query Language to query only a subset of the objects. You can also add an optional query name.

To add a subscription:

  1. Open the synced database.

  2. Call the getSubscriptions() method to interact with the subscription set.

  3. Open a subscription update block using SubscriptionSet.update().

  4. Use the MutableSubscriptionSet.addOrUpdate() method to append the new subscription to the subscription set.

  5. Call Subscription.create() with a query to a specific object type. Optionally, add a name for the query.

To add a subscription:

  1. Open the synced database.

  2. Access the database's subscriptions property.

  3. Open a subscription update block.

  4. Call the append method to append the new subscription to the subscription set.

  5. Pass a QuerySubscription<ObjectTypeName> with the name of the object type. Optionally, use the .where or NSPredicate query API to subscribe to only a subset of the objects of the type.

To add a subscription:

  1. Open the synced database.

  2. Access the database's realm.subscriptions property.

  3. Open a subscription update block.

  4. Create a subscription to a specific object type. Optionally add a query to subscribe to only a subset of the objects that match the query.

  5. Call the add() method with the subscription you just created to append the new subscription to the subscription set. Optionally, you can name the subscription.

auto updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.add<realm::Dog>("dogs");
})
.get();
// The .update() function returns a bool, which confirms whether or not the
// update succeeded
REQUIRE(updateSubscriptionSuccess == true);
// You can check the .size() of the subscription set, which tells you the
// number of sync_subscription objects in the set
CHECK(syncedRealm.subscriptions().size() == 1);

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();
var query = realm.All<Team>().Where(t => t.Name == "MyTeam");
await query.SubscribeAsync();
// you can also pass a SubscriptionOptions object:
var query2 = realm.All<Team>().Where(t => t.Name == "DevelopmentTeam");
await query2.SubscribeAsync(
new SubscriptionOptions() { Name = "devTeamSubscription" });
// The documentation does not currently have this code example in Dart.
// Please refer to the other languages or related pages for example code.
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create("my frog subscription",
realm.where(Frog.class)
.equalTo("name",
"Benedict Cumberburger")));
}
});
const tasks = realm.objects("Task");
const longRunningTasks = tasks.filtered(
'status == "completed" && progressMinutes > 120'
);
await realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(longRunningTasks, {
name: "longRunningTasksSubscription",
});
mutableSubs.add(realm.objects("Team"), {
name: "teamsSubscription",
});
});
realm.subscriptions.update {
add(
realm.query<Task>("progressMinutes >= $0",60)
)
}
realm.subscriptions.update { subscriptions ->
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create(
"my frog subscription",
realm.where(Frog::class.java)
.equalTo(
"name",
"Benedict Cumberburger"
)
)
)
}
let realm = try await getRealmWithSingleSubscription()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func getRealmWithSingleSubscription() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
try await subscriptions.update {
subscriptions.append(
QuerySubscription<Team> {
$0.teamName == "Developer Education"
})
}
return realm
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

If you add a duplicate unnamed subscription with the same query, the SDK automatically removes it; adding an identical named subscription is a no-op. Therefore, in both cases, duplicate subscriptions are ignored.

Subscription names must be unique. Adding a subscription with the same name as an existing subscription throws an error.

If you do not explicitly name a subscription, and instead subscribe to the same unnamed query more than once, the SDD does not persist duplicate queries to the subscription set.

If you subscribe to the same query more than once under different names, the SDK persists both subscriptions to the subscription set.

Subscription names must be unique. Adding a subscription with the same name as an existing subscription throws an error.

If you do not explicitly name a subscription, and instead subscribe to the same unnamed query more than once, the SDD does not persist duplicate queries to the subscription set.

If you subscribe to the same query more than once under different names, the SDK persists both subscriptions to the subscription set.

Subscription names must be unique. Trying to append a subscription with the same name as an existing subscription throws an error.

If you do not explicitly name a subscription, and instead subscribe to the same unnamed query more than once, the SDK does not persist duplicate queries to the subscription set.

If you subscribe to the same query more than once under different names, the SDK persists both subscriptions to the subscription set.

If your application flow appends the same named subscription to the subscription set every time you run the application, add a check for an existing subscription before appending it.

let realm = try await checkAndAddSubscription()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func checkAndAddSubscription() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
let foundSubscription = subscriptions.first(named: "user_team")
try await subscriptions.update {
if foundSubscription != nil {
foundSubscription!.updateQuery(toType: Team.self, where: {
$0.teamName == "Developer Education"
})
} else {
subscriptions.append(
QuerySubscription<Team>(name: "user_team") {
$0.teamName == "Developer Education"
})
}
}
return realm
}

If your app doesn't need to update or remove subscriptions, you can add a subscription without a name.

// The documentation does not currently have this code example in C++.
// Please refer to the other languages or related pages for example code.

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();
// The documentation does not currently have this code example in C#.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Dart.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Java.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in JavaScript.
// Please refer to the other languages or related pages for example code.
realm.subscriptions.update {
add(
realm.query<Task>("progressMinutes >= $0",60)
)
}
// The documentation does not have this code example in Kotlin for the Java SDK.
// Please refer to the other languages or related pages for example code.
QuerySubscription<Team> {
$0.teamName == "Developer Education"
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

If your app might need to update or remove subscriptions, you should add a name when you create a subscription. You can use the name to find and update or remove the appropriate subscription later.

updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.add<realm::Dog>(
"puppies", [](auto &obj) { return obj.age < 3; });
})
.get();
REQUIRE(updateSubscriptionSuccess == true);
CHECK(syncedRealm.subscriptions().size() == 1);

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();
// The documentation does not currently have this code example in C#.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Dart.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Java.
// Please refer to the other languages or related pages for example code.
const tasks = realm.objects("Task");
const longRunningTasks = tasks.filtered(
'status == "completed" && progressMinutes > 120'
);
await realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(longRunningTasks, {
name: "longRunningTasksSubscription",
});
mutableSubs.add(realm.objects("Team"), {
name: "teamsSubscription",
});
});
// Add a subscription named "team_dev_ed"
realm.subscriptions.update { realm ->
add(
realm.query<Team>("teamName == $0", "Developer Education"),
name = "team_dev_ed"
)
}
// The documentation does not have this code example in Kotlin for the Java SDK.
// Please refer to the other languages or related pages for example code.
QuerySubscription<Task>(name: "long-running-completed") {
$0.completed == true && $0.progressMinutes > 120
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

You can add multiple subscriptions within a subscription update block, including subscriptions of different object types.

Performing query updates requires Atlas to recalculate which documents match the query. We strongly advise designing your application to minimize updates. You can do this by batching additions and changes to the subscription set.

// The documentation does not currently have this code example in C++.
// Please refer to the other languages or related pages for example code.

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();

While you can add a single query using SubscribeAsync, you can only batch multiple queries within a SubscriptionSet.Update block.

realm.Subscriptions.Update(() =>
{
// Subscribe to all long running items, and name
// the subscription "longRunningItems"
var longRunningTasksQuery = realm.All<Item>()
.Where(t => t.ProgressMinutes > 120);
realm.Subscriptions.Add(longRunningTasksQuery,
new SubscriptionOptions() { Name = "longRunningItems" });
// Subscribe to all of Ben's Items
realm.Subscriptions.Add(realm.All<Item>()
.Where(t => t.Owner == "Ben"));
// Subscribe to all Teams, name the subscription
// 'teamsSubscription', and throw an error if
// this subscription name already exists.
realm.Subscriptions.Add(realm.All<Team>(),
new SubscriptionOptions()
{ Name = "teams", UpdateExisting = false });
});
final planeQuery = realm.all<Plane>();
final longTrainQuery = realm.query<Train>("numCars >= 5");
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.add(planeQuery, name: "planes");
mutableSubscriptions.add(longTrainQuery,
name: 'long-trains', update: true);
});
await realm.subscriptions.waitForSynchronization();
// The documentation does not have this code example in Java.
// Please refer to the other languages or related pages for example code.
const tasks = realm.objects("Task");
const longRunningTasks = tasks.filtered(
'status == "completed" && progressMinutes > 120'
);
await realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(longRunningTasks, {
name: "longRunningTasksSubscription",
});
mutableSubs.add(realm.objects("Team"), {
name: "teamsSubscription",
});
});
// The documentation does not currently have this code example in Kotlin.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Kotlin for the Java SDK.
// Please refer to the other languages or related pages for example code.
let realm = try await getRealmWithMultipleSubscriptions()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func getRealmWithMultipleSubscriptions() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
try await subscriptions.update {
subscriptions.append(
QuerySubscription<Task>(name: "completed-tasks") {
$0.completed == true
})
subscriptions.append(
QuerySubscription<Team> {
$0.teamName == "Developer Education"
})
}
return realm
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

In addition to syncing all objects that match a given query, you can subscribe to all objects of a specific type. You do this by appending a subscription without providing a query.

auto updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.add<realm::Dog>("dogs");
})
.get();
// The .update() function returns a bool, which confirms whether or not the
// update succeeded
REQUIRE(updateSubscriptionSuccess == true);
// You can check the .size() of the subscription set, which tells you the
// number of sync_subscription objects in the set
CHECK(syncedRealm.subscriptions().size() == 1);

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();
// The documentation does not currently have this code example in C#.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Dart.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Java.
// Please refer to the other languages or related pages for example code.
const tasks = realm.objects("Task");
const longRunningTasks = tasks.filtered(
'status == "completed" && progressMinutes > 120'
);
await realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(longRunningTasks, {
name: "longRunningTasksSubscription",
});
mutableSubs.add(realm.objects("Team"), {
name: "teamsSubscription",
});
});
// The documentation does not currently have this code example in Kotlin.
// Please refer to the other languages or related pages for example code.
// The documentation does not have this code example in Kotlin for the Java SDK.
// Please refer to the other languages or related pages for example code.
let realm = try await subscribeToObjectsOfAType()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func subscribeToObjectsOfAType() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
try await subscriptions.update {
subscriptions.append(QuerySubscription<Team>(name: "all_teams"))
}
XCTAssertEqual(subscriptions.count, 1) // :remove
return realm
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

You must have at least one subscription before you can read from or write to the database. You can bootstrap the database with an initial subscription set when you open it. This ensures your app can start working with the database successfully right away.

The selected language does not provide a dedicated API to set initial subscriptions. Instead, refer to the Add a Subscription section on this page.

You can bootstrap the database with an initial subscription set when you open it with a FlexibleSyncConfiguration. Set the PopulateInitialSubscriptions parameter to a callback that is invoked when the database instance is created. Add the queries you want to use to bootstrap the database, as shown in the following example.

The selected language does not provide a dedicated API to set initial subscriptions. Instead, refer to the Add a Subscription section on this page.

The selected language does not provide a dedicated API to set initial subscriptions. Instead, refer to the Add a Subscription section on this page.

To set initial subscriptions, include the initialSubscriptions field in your realm's SyncConfiguration. Within the initialSubscriptions object, add an update field set to a callback that subscribes to queries.

By default, initial subscriptions are only created the first time the database is opened. If your app needs to rerun this initial subscription every time the app starts, you can set rerunOnOpen to true. You might need to do this to re-run dynamic time ranges or other queries that require a re-computation of static variables for the subscription.

You can bootstrap the database with an initial subscription set when you open it with the SyncConfiguration().

Pass the initialSubscriptions parameter with the subscription queries you want to use to bootstrap the database:

// Bootstrap the realm with an initial query to subscribe to
val flexSyncConfig =
SyncConfiguration.Builder(user, setOf(Team::class, Task::class))
.initialSubscriptions { realm ->
add(
realm.query<Team>("$0 IN members", "Bob Smith"),
"bob_smith_teams"
)
}
.build()

If your app needs to rerun this initial subscription every time the app starts, you can pass an additional parameter: rerunOnOpen. This is a boolean that denotes whether the initial subscription should re-run every time the app starts. You might need to do this to re-run dynamic time ranges or other queries that require a re-computation of static variables for the subscription.

In this example, we only want incomplete tasks. With rerunOnOpen set to true, the query dynamically recalculates the relevant objects to sync based on the desired query results every time the app starts.

The selected language does not provide a dedicated API to set initial subscriptions. Instead, refer to the Add a Subscription section on this page.

You can set initial subscriptions through the flexibleSyncConfiguration(). Pass the initialSubscriptions parameter with the subscription queries you want to use to bootstrap the database:

var flexSyncConfig = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
subs.append(
QuerySubscription<Team> {
$0.teamName == "Developer Education"
})
})

If your app needs to rerun this initial subscription every time the app starts, you can pass an additional parameter - rerunOnOpen. This is a bool that denotes whether the initial subscription should re-run every time the app starts. You might need to do this to re-run dynamic time ranges or other queries that require a re-computation of static variables for the subscription.

In this example, we don't want users to be overwhelmed by irrelevant tasks, so we'll load only tasks due within the previous 7 days and the next 7 days. Tasks that were due more than a week ago are no longer relevant, and tasks that are due further out than the next week are also not relevant. With rerunOnOpen here, the query dynamically recalculates the relevant objects to sync based on the desired date range every time the app starts.

To set initial subscriptions, include the initialSubscriptions field in your realm's SyncConfiguration. Within the initialSubscriptions object, add an update field set to a callback that subscribes to queries.

By default, initial subscriptions are only created the first time the database is opened. If your app needs to rerun this initial subscription every time the app starts, you can set rerunOnOpen to true. You might need to do this to re-run dynamic time ranges or other queries that require a re-computation of static variables for the subscription.

// The C++ SDK does not currently support this API.
var config = new FlexibleSyncConfiguration(app.CurrentUser)
{
PopulateInitialSubscriptions = (realm) =>
{
var myItems = realm.All<Item>().Where(n => n.OwnerId == myUserId);
realm.Subscriptions.Add(myItems);
}
};
// The process will complete when all the user's items have been downloaded.
var realm = await Realm.GetInstanceAsync(config);
// The Flutter SDK does not currently support this API.
// The Java SDK does not support this API.
const config = {
schema: [Task],
sync: {
user: app.currentUser,
flexible: true,
initialSubscriptions: {
update: (subs, realm) => {
subs.add(realm.objects(Task).filtered("status == 'in progress'"), {
name: "In progress tasks",
});
},
rerunOnOpen: true,
},
},
};
const realm = await Realm.open(config);
// `rerunOnOpen` lets the app recalculate this query every time the app opens
val rerunOnOpenConfig =
SyncConfiguration.Builder(user, setOf(Team::class, Task::class))
.initialSubscriptions(rerunOnOpen = true) { realm ->
add(
realm.query<Team>("completed == $0", false)
)
}
.build()
// The Java SDK does not support this API.
// Set the date a week ago and the date a week from now, as those are the dates we'll use
// in the Flexible Sync query. `rerunOnOpen` lets the app recalculate this query every
// time the app opens.
let secondsInAWeek: TimeInterval = 604800
let dateLastWeek = (Date.now - secondsInAWeek)
let dateNextWeek = (Date.now + secondsInAWeek)
var flexSyncConfig = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
subs.append(
QuerySubscription<Task> {
$0.dueDate > dateLastWeek && $0.dueDate < dateNextWeek
})
}, rerunOnOpen: true)
const config: Realm.Configuration = {
schema: [Task],
sync: {
user: app.currentUser!,
flexible: true,
initialSubscriptions: {
update: (subs, realm) => {
subs.add(realm.objects(Task).filtered("status == 'in progress'"), {
name: "In progress tasks",
});
},
rerunOnOpen: true,
},
},
};
const realm = await Realm.open(config);

At any point after setting initial subscriptions, you can:

Updating the subscription set on the device is only one component of changing a subscription. After the client app subscription change, the SDK synchronizes with the server to resolve any updates to the data due to the subscription change. This could mean adding or removing data from the synced database.

Adding New Subscriptions

If your app creates objects, you may not need to download synced data before the user works with it. However, if your app requires data from Atlas before the user can work with your app, you can specify that the SDK should wait for the subscription changes to sync before proceeding.

Updating Existing Subscriptions

When you update an existing subscription, this could mean adding new data or removing data from the synced database. If this involves things like changing user permissions to add or remove data, or if your app otherwise makes these changes visible to users in the UI, you may want to wait for subscription changes to update before proceeding with app execution. Otherwise, the changes may appear to the user as unexpected changes to the data set later during "normal" app execution.

C++ does not currently provide an API to wait for subscription changes to sync.

Use the SubscriptionSet.WaitForSynchronizationAsync() method to wait for the server to acknowledge this set of subscriptions. If the server rejects the change, the SubscriptionSetState will be an error state, and an exception will be thrown.

An exception may occur if:

  • An unsupported query is subscribed to. Subscribing to an unsupported query will pause synchronization. To resume synchronization, remove the unsupported query.

  • You are performing an invalid action, such as adding an object that does not match a subscription. This triggers a client reset: data is erased from the device, and a new copy of the data is created without any subscriptions in the set.

Use Realm.subscriptions.waitForSynchronization() to wait for the server to acknowledge this set of subscriptions. If the server rejects the change, and an exception is thrown.

An exception may occur if:

  • You subscribe to an unsupported query. Subscribing to an unsupported query will pause synchronization. To resume synchronization, remove the unsupported query.

  • You are performing an invalid action, such as adding an object that does not match a subscription. This triggers a client reset: data is erased from the device, and a new copy of the data is created without any subscriptions in the set.

Use the waitForInitialRemoteData() builder method to force your application to block until client subscription data synchronizes to the backend before opening the database.

Alternately, you could use SubscriptionSet.waitForSynchronization() or SubscriptionSet.waitForSynchronizationAsync() to delay execution until subscription sync completes after instantiating a sync connection.

You can wait for subscription changes to sync in two ways:

  • await the call to SubscriptionSet.update(), which returns a promise that resolves when the SubscriptionSet is synchronized, or is rejected if there was an error during synchronization.

  • Explicitly call SubscriptionSet.waitForSynchronization() to wait for the server to acknowledge this set of subscriptions and return the matching objects, or throw an error.

Use the SyncConfiguration.waitForInitialRemoteData() builder method to force your application to block until client subscription data synchronizes to the backend before opening the database.

Alternately, you can use SubscriptionSet.waitForSynchronization() to delay execution until subscription sync completes after instantiating a sync connection.

Use the waitForInitialRemoteData() builder method to force your application to block until client subscription data synchronizes to the backend before opening the database.

Alternately, you could use SubscriptionSet.waitForSynchronization() or SubscriptionSet.waitForSynchronizationAsync() to delay execution until subscription sync completes after instantiating a sync connection.

If your application uses async/await, you don't need the onComplete block. The update executes asynchronously and throws an error if the update cannot complete successfully.

@MainActor
func changeSubscription() async throws {
let subscriptions = realm.subscriptions
try await subcriptions.update {
subscriptions.remove {
QuerySubscription<Task> {
$0.assignee == "Joe Doe"
}
}
}
}

If your application does not use Swift's async/await feature, you can react to subscription changes syncing with the server using the onComplete block. This block is called after subscriptions are synchronized with the server. If you want to react to subscription state changes by redrawing a UI, for example, or taking another action based on changes to the data set, take those actions in onComplete. This is also where you can handle optional errors that occur during synchronization.

You can wait for subscription changes to sync in two ways:

  • await the call to SubscriptionSet.update(), which returns a promise that resolves when the SubscriptionSet is synchronized, or is rejected if there was an error during synchronization.

  • Explicitly call SubscriptionSet.waitForSynchronization() to wait for the server to acknowledge this set of subscriptions and return the matching objects, or throw an error.

// The C++ SDK does not currently support this API.
try
{
await realm.Subscriptions.WaitForSynchronizationAsync();
}
catch (SubscriptionException ex)
{
// do something in response to the exception or log it
Console.WriteLine($@"The subscription set's state is Error and synchronization is paused: {ex.Message}");
}
await realm.subscriptions.waitForSynchronization();
SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
@Override
public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
subscriptions.add(Subscription.create("my subscription",
realm.where(Frog.class)
.equalTo("species", "poison dart")));
}
})
.waitForInitialRemoteData(2112, TimeUnit.MILLISECONDS)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
}
});
// The documentation does not currently have this code example in JavaScript.
// Please refer to the other languages or related pages for example code.
// Update the list of subscriptions
realm.subscriptions.update {
add(
realm.query<Team>("$0 IN members", "Jane Doe"),
"jane_doe_teams"
)
}
// Wait for subscription to fully synchronize changes
realm.subscriptions.waitForSynchronization(Duration.parse("10s"))
val config = SyncConfiguration.Builder(app.currentUser())
.initialSubscriptions { realm, subscriptions ->
subscriptions.add(
Subscription.create(
"my subscription",
realm.where(Frog::class.java)
.equalTo("species", "poison dart")
)
)
}
.waitForInitialRemoteData(
2112,
TimeUnit.MILLISECONDS
)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm.")
}
})
let subscriptions = realm.subscriptions
subscriptions.update({
subscriptions.append(
QuerySubscription<Task> {
$0.assignee == "John Doe"
})
}, onComplete: { error in // error is optional
if error == nil {
// Flexible Sync has updated data to match the subscription
} else {
// Handle the error
}
})
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

You can check the state of the subscription set through to find out the current status of the subscription set. This provides information about whether Atlas has registered the subscription that is on the device. It does not make any guarantees about the state of the documents matching the subscription.

C++ does not currently provide an API to check the state of a subscription set.

Use the SubscriptionSet.State property to read the current state of the subscription set.

The Superseded state is a SubscriptionSetState that can occur when another thread updates a subscription on a different instance of the subscription set. If the state becomes Superseded, you must obtain a new instance of the subscription set before you can update it.

Use the Realm.subscriptions.state property to read the current state of the subscription set.

The superseded state is a SubscriptionSetState that can occur when another thread updates a subscription on a different instance of the subscription set. If the state becomes superseded, you must obtain a new instance of the subscription set before you can update it.

You can watch the state of the subscription set with the SubscriptionSet.State enum. You can use subscription state to:

  • Show a progress indicator while data is downloading

  • Find out when a subscription set becomes superseded

You can access the state of your application's subscription set using SubscriptionSet.getState().

SUPERSEDED is a SubscriptionSet.State that can occur when another thread writes a subscription on a different instance of the subscription set. If the state becomes SUPERSEDED, you must obtain a new instance of the subscription set before you can write to it.

You can check the subscription state to see if the server has acknowledged the subscription and the device has downloaded the data locally.

You can use subscription state to:

  • Trigger error handling

  • Show if the transaction is pending or has completed

  • Find out when a subscription set is superseded, and you should obtain a new instance of the subscription set to write a subscription change

The SubscriptionSetState enum provides information about the status of a subscription.

Use the SubscriptionSet.state property to read the current state of the subscription set.

SUPERCEDED (sic -- note alternate spelling) is a SubscriptionSetState that can occur when another thread writes a subscription on a different instance of the subscription set. If the state becomes SUPERCEDED, you must obtain a new instance of the subscription set before you can write to it.

You can watch the state of the subscription set with the SubscriptionSet.State enum. You can use subscription state to:

  • Show a progress indicator while data is downloading

  • Find out when a subscription set becomes superseded

You can access the state of your application's subscription set using SubscriptionSet.getState().

SUPERSEDED is a SubscriptionSet.State that can occur when another thread writes a subscription on a different instance of the subscription set. If the state becomes SUPERSEDED, you must obtain a new instance of the subscription set before you can write to it.

Use the SubscriptionSet.state property to read the current state of the subscription set.

The superseded state is a SyncSubscriptionState that can occur when another thread updates a subscription on a different instance of the subscription set. If the state becomes superseded, you must obtain a new instance of the subscription set before you can update it.

You can check the subscription state to see if the server has acknowledged the subscription and the device has downloaded the data locally.

You can use subscription state to:

  • Trigger error handling

  • Show if the transaction is pending or has completed

  • Find out when a subscription set is superseded, and you should obtain a new instance of the subscription set to write a subscription change

The SubscriptionSetState enum provides information about the status of a subscription.

Note

Subscription State "Complete"

The subscription set state "complete" does not mean "sync is done" or "all documents have been synced". "Complete" means the following two things have happened:

  • The subscription has become the active subscription set that is currently being synchronized with the server.

  • The documents that matched the subscription at the time the subscription was sent to the server are now on the device. Note that this does not necessarily include all documents that currently match the subscription.

The SDK does not provide a way to check whether all documents that match a subscription have synced to the device.

You can change the queries in a subscription set. You might want to do this when business logic dictates syncing a different subset of objects, such as when a user unlocks new features in an app.

  • Change a named query

  • Change an unnamed query

When you change a query, consider how it interacts with any other queries that may be in the subscription set. You may need to add or remove other subscriptions, such as:

  • Adding a new subscription when a change to a query introduces new linked objects

  • Removing a subscription when an overlapping query inadvertently exposes objects you don't want to sync

To update a subscription set, use the subscription().updates() function. This gives you access to a mutable_sync_subscription_set where you can use the update_subscription() function to update a specific sync_subscription.

You can change a sync_subscription's query in an update. You can add, remove, or update the query string for a given sync_subscription.

You can update a named subscription with a new query. To update a subscription's query, pass the new query and a subscription option with the name of the subscription that you want to update to the SubscriptionSet.Add() method. Like adding a new subscription, you must update a subscription within an update block by calling SubscriptionSet.Update() method.

The SubscriptionOptions.UpdateExisting field must be set to true, or else attempting to change the subscription throws an exception.

In the following example, long running tasks are re-defined to be any tasks that have taken more than 130 minutes.

You can update a named subscription with a new query. To update a subscription's query, open an update block with SubscriptionSet.update(). In the callback function of the update block, pass the following arguments to MutableSubscriptionSet.add():

  • The new query

  • The name of the subscription that you want to update

  • update: true

In the following example, long trains are re-defined to be any trains that have more than 10 cars.

You can update subscriptions using SubscriptionSet.update(). In this example, we use MutableSubscriptionSet.addOrUpdate() to update the query for the subscription named "my frog subscription".

You can update a named subscription with a new query. To update a subscription's query, pass the new query and a subscription option with the name of the subscription that you want to update to the MutableSubscriptionSet.add() method. Like adding a new subscription, you must update a subscription within a transaction by calling subscriptions.update().

The SubscriptionOptions.throwOnUpdate field must be set to false, or else attempting to change the subscription throws an exception.

In the following example, long-running tasks are re-defined to be any tasks that have taken more than 180 minutes.

You can update subscriptions using SubscriptionSet.update().

In this example, we use MutableSubscriptionSet.add(). to update the query for the subscription named "bob_smith_teams".

You must set the updateExisting parameter to true to update a subscription - otherwise the SDK throws an exception.

You can update subscriptions using SubscriptionSet.update(). In this example, we use MutableSubscriptionSet.addOrUpdate() to update the query for the subscription named "my frog subscription".

You can search for a subscription by name, and then update the named subscription.

To change a subscription query, call the updateQuery method on an existing query inside a subscriptions.update block.

You can update a named subscription with a new query. To update a subscription's query, pass the new query and a subscription option with the name of the subscription that you want to update to the MutableSubscriptionSet.add() method. Like adding a new subscription, you must update a subscription within a transaction by calling subscriptions.update().

The SubscriptionOptions.throwOnUpdate field must be set to false, or else attempting to change the subscription throws an exception.

In the following example, long-running tasks are re-defined to be any tasks that have taken more than 180 minutes.

updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.update_subscription<realm::Dog>(
"puppies", [](auto &obj) { return obj.age < 2; });
})
.get();
REQUIRE(updateSubscriptionSuccess == true);

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();
realm.Subscriptions.Update(() =>
{
var updatedLongRunningTasksQuery = realm.All<Item>()
.Where(t => t.Status == "completed" && t.ProgressMinutes > 130);
realm.Subscriptions.Add(updatedLongRunningTasksQuery,
new SubscriptionOptions() { Name = "longRunningTasks" });
});
final longerTrainQuery = realm.query<Train>("numCars > 10");
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.add(longerTrainQuery,
name: 'long-trains', update: true);
});
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create("my frog subscription",
realm.where(Frog.class)
.equalTo("name",
"Benedict Cumberburger")));
}
});
realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(
tasks.filtered('status == "completed" && progressMinutes > 180'),
{
name: "longRunningTasksSubscription",
}
);
});
// Create a subscription named "bob_smith_teams"
realm.subscriptions.update {
add(
realm.query<Team>("$0 IN members", "Bob Smith"),
"bob_smith_teams"
)
}
// Set `updateExisting` to true to replace the existing
// "bob_smith_teams" subscription
realm.subscriptions.update {
add(
realm.query<Team>("$0 IN members AND $1 IN members", "Bob Smith", "Jane Doe"),
"bob_smith_teams", updateExisting = true
)
}
realm.subscriptions.update { subscriptions ->
// to update a named subscription, create a replacement with
// the same name and add it to the subscription set
subscriptions.addOrUpdate(
Subscription.create(
"my frog subscription",
realm.where(Frog::class.java)
.equalTo(
"name",
"Benedict Cumberburger"
)
)
)
}
let realm = try await getRealmWithUpdatedSubscriptionName()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func getRealmWithUpdatedSubscriptionName() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
let foundSubscription = subscriptions.first(named: "user-team")
try await subscriptions.update {
foundSubscription?.updateQuery(toType: Team.self, where: {
$0.teamName == "Documentation"
})
}
return realm
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

C++ does not provide the ability to change an unnamed subscription. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can remove all subscriptions, and create new subscriptions with the desired query.

C# does not provide the ability to change an unnamed subscription. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can delete the unnamed subscription, and create a new subscription with the desired query.

Dart does not provide the ability to change an unnamed subscription. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can delete the unnamed subscription, and create a new subscription with the desired query.

The Java SDK does not support updating subscriptions created without a name. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can look up unnamed subscriptions by query, remove them from the subscription set, and create a new subscription with the desired query.

The JS SDK does not provide the ability to change an unnamed subscription. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can delete the unnamed subscription, and create a new subscription with the desired query.

Kotlin does not provide the ability to change an unnamed subscription. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can delete the unnamed subscription, and create a new subscription with the desired query.

The Java SDK does not support updating subscriptions created without a name. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can look up unnamed subscriptions by query, remove them from the subscription set, and create a new subscription with the desired query.

To change a subscription query, call the updateQuery method on an existing query inside a subscriptions.update block.

In this example, we search for a subscription matching our query and then update it with a new query.

The JS SDK does not provide the ability to change an unnamed subscription. If you know in advance that your app may need to change subscriptions, create the subscription with a name.

Alternately, you can delete the unnamed subscription, and create a new subscription with the desired query.

// The C++ SDK does not currently support this API.
// The .NET SDK does not currently support this API.
// The Flutter SDK does not currently support this API.
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
// to update an unnamed subscription, remove it from the
// subscription set, then add your new query to the set
Subscription mySubscription = subscriptions.find(realm.where(Frog.class)
.equalTo("species",
"cane toad"));
subscriptions.remove(mySubscription);
subscriptions.addOrUpdate(
Subscription.create(
realm.where(Frog.class)
.equalTo("species",
"albino cane toad")));
}
});
// The Node.js SDK does not currently support this API.
// Search for the subscription by query
val subscription =
realm.subscriptions.findByQuery(
realm.query<Team>("teamName == $0", "Developer Education")
)
// Remove the returned subscription and add the updated query
if (subscription != null) {
realm.subscriptions.update {
remove(subscription)
add(
realm.query<Team>("teamName == $0", "DevEd"),
"team_developer_education"
)
}
}
realm.subscriptions.update { subscriptions ->
// to update an unnamed subscription, remove it from the
// subscription set, then add your new query to the set
val mySubscription =
subscriptions.find(
realm.where(
Frog::class.java
).equalTo(
"species",
"cane toad"
)
)
subscriptions.remove(mySubscription)
subscriptions.addOrUpdate(
Subscription.create(
realm.where(Frog::class.java)
.equalTo(
"species",
"albino cane toad"
)
)
)
}
let realm = try await getRealmWithUpdatedSubscriptions()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func getRealmWithUpdatedSubscriptions() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
try await subscriptions.update {
if let foundSubscription = subscriptions.first(ofType: Team.self, where: {
$0.teamName == "Developer Education"
}) {
foundSubscription.updateQuery(toType: Team.self, where: {
$0.teamName == "Documentation"
})
}
}
return realm
}
// This API is not currently available in TypeScript.

To remove subscriptions, you can:

  • Remove a specific subscription

    • Remove a named subscription

    • Remove an unnamed subscription

    • Remove a subscription by reference

  • Remove all subscriptions for a specific object type

  • Remove all unnamed subscriptions

  • Remove all subscriptions

When you remove a subscription query, the SDK asynchronously removes the synced data that matched the query from the client device.

You can remove a specific subscription by name using the remove() function inside a subscription().updates() block. Removing a subscription by name throws an error if the subscription does not exist, so you should check for a subscription before removing it.

Within an update block, you can remove a specific subscription by name. Pass the name to the Remove() method on the SubscriptionSet.

You can update a named subscription with a new query. To update a subscription's query, open an update block with SubscriptionSet.update(). In the callback function of the update block, pass the following arguments to MutableSubscriptionSet.add():

  • The new query

  • The name of the subscription that you want to update

  • update: true

In the following example, long trains are re-defined to be any trains that have more than 10 cars.

You can remove a specific subscription query using MutableSubscriptionSet.remove(). The remove() method takes a subscription name, or a reference to the subscription itself.

To remove a specific subscription by name, execute a transaction on the subscriptions set. Within the transaction, pass the name to the removeByName() method on the MutableSubscriptionSet.

You can remove a named subscription query by passing the subscription name to MutableSubscriptionSet.remove().

You can remove a specific subscription query using MutableSubscriptionSet.remove(). The remove() method takes a subscription name, or a reference to the subscription itself.

You can remove a specific named subscription by passing the name to the remove() method in a subscription update block.

To remove a specific subscription by name, execute a transaction on the subscriptions set. Within the transaction, pass the name to the removeByName() method on the MutableSubscriptionSet.

auto removeSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.remove("dogs");
})
.get();
REQUIRE(removeSubscriptionSuccess == true);

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();
realm.Subscriptions.Update(() =>
{
// remove a named subscription
var subscriptionName = "longRunningItemsSubscription";
realm.Subscriptions.Remove(subscriptionName);
});
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByName('long-trains');
});
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
Subscription mySubscription = subscriptions.find("mySubscription");
subscriptions.remove(mySubscription);
}
});
realm.subscriptions.update((mutableSubs) => {
// remove a subscription with a specific name
mutableSubs.removeByName("longRunningTasksSubscription");
});
realm.subscriptions.update {
add(
realm.query<Team>("$0 IN members", "Bob Smith"),
"bob_smith_teams"
)
}
// Wait for synchronization to complete before updating subscriptions
realm.subscriptions.waitForSynchronization(Duration.parse("10s"))
// Remove subscription by name
realm.subscriptions.update {
remove("bob_smith_teams")
}
realm.subscriptions.update { subscriptions ->
val mySubscription =
subscriptions.find("mySubscription")
subscriptions.remove(mySubscription)
}
let realm = try await getRealmAfterRemovingSubscription()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func getRealmAfterRemovingSubscription() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
// Look for a specific subscription, and then remove it
let foundSubscription = subscriptions.first(named: "docs-team")
try await subscriptions.update {
subscriptions.remove(foundSubscription!)
}
// Or remove a subscription that you know exists without querying for it
try await subscriptions.update {
subscriptions.remove(named: "existing-subscription")
}
return realm
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

C++ does not provide the ability to remove a single unnamed subscription. If you know in advance that your app may need to remove subscriptions, create the subscription with a name.

Alternately, you can remove all subscriptions, and then add subscriptions that your app still needs.

Within an update block, you can remove an unnamed subscription by its query. Pass the query to the Remove() method on the SubscriptionSet.

In the following example, the subscription to tasks with an owner named 'Ben' is removed from the subscriptions set.

Within an update block, you can remove a specific subscription by query. Open an update block with SubscriptionSet.update(). Pass the Subscription to MutableSubscriptionSet.removeByQuery().

In the following example, the subscription for all Plane objects is removed.

The Java SDK does not provide a method to remove an unnamed subscription directly. However, you can look up a subscription by query, and pass the subscription to the MutableSubscriptionSet.remove() method to remove it from the subscription set.

You can remove a specific subscription by query by executing a transaction on the subscriptions set. Pass the query to the remove() method on the MutableSubscriptionSet within a transaction.

In the following example, the subscription to tasks with an owner named 'Ben' is removed from the subscriptions set.

Kotlin does not provide an API to directly remove an unnamed subscription. However, you can you can look up the subscription by query and then pass the reference to the subscription to MutableSubscriptionSet.remove().

The Java SDK does not provide a method to remove an unnamed subscription directly. However, you can look up a subscription by query, and pass the subscription to the MutableSubscriptionSet.remove() method to remove it from the subscription set.

You can remove a specific subscription query in a subscription update block by calling remove. You can find a subscription matching the query to remove the appropriate subscription.

You can remove a specific subscription by query by executing a transaction on the subscriptions set. Pass the query to the remove() method on the MutableSubscriptionSet within a transaction.

// The C++ SDK does not currently support this API.
realm.Subscriptions.Update(() =>
{
// remove a subscription by it's query
var query = realm.All<Item>().Where(i => i.Owner == "Ben");
realm.Subscriptions.Remove(query);
});
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByQuery(realm.all<Plane>());
});
// The Java SDK does not support this API.
realm.subscriptions.update((mutableSubs) => {
// remove a subscription with a specific query
mutableSubs.remove(tasks.filtered('owner == "Ben"'));
});
// The documentation does not currently have this code example in Kotlin.
// Please refer to the other languages or related pages for example code.
// The Kotlin SDK does not currently support this API.
// The documentation does not currently have this code example in Swift.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

C++ does not provide the ability to remove a subscription by reference. If you know in advance that your app may need to remove subscriptions, create the subscription with a name.

Alternately, you can remove all subscriptions, and then add subscriptions that your app still needs.

Within an update block, you can remove a specific subscription by reference. Pass the subscription to the Remove() method on the SubscriptionSet.

You can remove a subscription if you have a reference to its Subscription object. Within a subscription update block, pass the Subscription reference to MutableSubscriptionSet.remove().

You can remove a subscription by reference when you pass the subscription to the MutableSubscriptionSet.remove() method.

If you have a reference to a subscription, you can remove that subscription. To do so, execute a transaction on the subscriptions set. Within the transaction, pass the reference variable to the removeSubscription method on the MutableSubscriptionSet.

You can remove a subscription by reference by passing the subscription to MutableSubscriptionSet.remove().

You can remove a subscription by reference when you pass the subscription to the MutableSubscriptionSet.remove() method.

You can remove a subscription by reference by passing the subscription to the remove() method in a subscription update block.

If you have a reference to a subscription, you can remove that subscription. To do so, execute a transaction on the subscriptions set. Within the transaction, pass the reference variable to the removeSubscription method on the MutableSubscriptionSet.

// The C++ SDK does not currently support this API.
// The documentation does not currently have this code example in C#.
// Please refer to the other languages or related pages for example code.
final sub = realm.subscriptions[0];
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.remove(sub);
});
// The documentation does not have this code example in Java.
// Please refer to the other languages or related pages for example code.
let subscriptionReference;
realm.subscriptions.update((mutableSubs) => {
subscriptionReference = mutableSubs.add(realm.objects("Task"));
});
// later..
realm.subscriptions.removeSubscription(subscriptionReference);
// The documentation does not currently have this code example in Kotlin.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Kotlin.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Swift.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

C++ does not provide the ability to remove all subscriptions to a specific object type. If you know in advance that your app may need to remove subscriptions, create the subscription with a name.

Alternately, you can remove all subscriptions, and then add subscriptions that your app still needs.

Within an update block, you can remove remove all unnamed subscriptions of a class by passing the class name as a string to the RemoveAll("ClassName") method. The RemoveAll() method has an optional second argument that is a boolean, removedName, which also removes the named subscriptions if it is set to true. removedName is set to false by default.

Alternatively, you can remove all unnamed subscriptions of an object type with RemoveAll(). The RemoveAll<Type>() method has an optional boolean removedName argument that also removes the named subscriptions if it is set to true. The removedName argument is set to false by default.

You can remove all subscriptions for a given SDK object type. Within a subscription update block, call MutableSubscriptionSet.removeByType().

If you want to remove all subscriptions to a specific object type, pass a class to the removeAll() method.

To remove all subscriptions on a specific object type, execute a transaction on the subscriptions set. Within the transaction, pass the object type as a string to the removeByObjectType method on the MutableSubscriptionSet.

If you want to remove all subscriptions to a specific object type, pass a class to the MutableSubscriptionSet.removeAll() method.

If you want to remove all subscriptions to a specific object type, pass a class to the removeAll() method.

You can remove all subscriptions to a specific object type by calling the removeAll method with an ofType argument in a subscription update block.

To remove all subscriptions on a specific object type, execute a transaction on the subscriptions set. Within the transaction, pass the object type as a string to the removeByObjectType method on the MutableSubscriptionSet.

// The C++ SDK does not currently support this API.
realm.Subscriptions.Update(() =>
{
// remove all subscriptions of the "Team" Class Name
realm.Subscriptions.RemoveAll("Team");
// Alernatively, remove all subscriptions of the "Team" object type
realm.Subscriptions.RemoveAll<Team>();
});
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByType<Train>();
});
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
subscriptions.removeAll(Frog.class);
}
});
realm.subscriptions.update((mutableSubs) => {
mutableSubs.removeByObjectType("Team");
});
realm.subscriptions.update {
add(
realm.query<Team>("$0 IN members", "Bob Smith"),
"bob_smith_teams")
}
// Wait for synchronization to complete before updating subscriptions
realm.subscriptions.waitForSynchronization(Duration.parse("10s"))
// Remove all subscriptions to type Team
realm.subscriptions.update {
removeAll(Team::class)
}
realm.subscriptions.update { subscriptions ->
subscriptions.removeAll(
Frog::class.java
)
}
let realm = try await getRealmAfterRemovingAllSubscriptionsToAnObjectType()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func getRealmAfterRemovingAllSubscriptionsToAnObjectType() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
try await subscriptions.update {
subscriptions.removeAll(ofType: Team.self)
}
return realm
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

You may want to remove unnamed subscriptions that are transient or dynamically generated, but leave named subscriptions in place.

C++ does not provide the ability to remove all unnamed subscriptions.

Instead, you can remove all subscriptions, and then add subscriptions that your app still needs.

Within an update block, you can remove all unnamed subscriptions from the subscriptions set. Call the RemoveAll() method on the SubscriptionSet, with the optional boolean removedName argument set to false. This removes only unnamed subscriptions.

Within a subscription update block, you can remove all unnamed subscriptions from the subscriptions set by calling MutableSubscriptionSet.clear() with an unnamedOnly argument set to true.

The Java SDK does not provide a method to remove all unnamed subscriptions.

Instead, you can remove all subscriptions from the subscription set, with removeAll(). Then, create the new subscriptions that your app needs.

You can remove all unnamed subscriptions from the subscription set by calling .removeUnnamed() on mutableSubs. .removeUnnamed() returns the number of unnamed subscriptions removed.

You can remove all unnamed (anonymous) subscriptions from the subscription set by setting anonymousOnly to true when you call the removeAll method.

The Java SDK does not provide a method to remove all unnamed subscriptions.

Instead, you can remove all subscriptions from the subscription set, with removeAll(). Then, create the new subscriptions that your app needs.

You can remove all unnamed subscriptions from the subscription set by setting unnamedOnly to true when you call the removeAll method.

You can remove all unnamed subscriptions from the subscription set by calling .removeUnnamed() on mutableSubs. .removeUnnamed() returns the number of unnamed subscriptions removed.

// The C++ SDK does not currently support this API.
// The documentation does not currently have this code example in C#.
// Please refer to the other languages or related pages for example code.
// The documentation does not currently have this code example in Dart.
// Please refer to the other languages or related pages for example code.
// The Java SDK does not support this API.
// Remove unnamed subscriptions.
let numberRemovedSubscriptions = 0;
await realm.subscriptions.update((mutableSubs) => {
numberRemovedSubscriptions = mutableSubs.removeUnnamed();
});
// Remove all unnamed (anonymous) subscriptions
realm.subscriptions.update {
removeAll(anonymousOnly = true)
}
// The Kotlin SDK does not currently support this API.
let realm = try await Realm(configuration: flexSyncConfig)
// Add 2 subscriptions, one named and one unnamed.
let results = try await realm.objects(Team.self).where { $0.teamName == "Developer Education" }.subscribe(name: "team_developer_education")
let results2 = try await realm.objects(Task.self).where { $0.completed == false }.subscribe()
// Later, remove only the unnamed one
let subscriptions = realm.subscriptions
try await subscriptions.update {
subscriptions.removeAll(unnamedOnly: true)
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

Important

If you remove all subscriptions and do not add a new one, you'll get an error. A database opened with a flexible sync configuration needs at least one subscription to sync with the server.

You can remove all subscriptions in a subscription set using the clear() function.

Within an update block, you can remove all subscriptions from the subscriptions set. Call the RemoveAll() method on the SubscriptionSet.

By default, the RemoveAll() method only removes unnamed subscriptions. Set the optional removedName boolean to true to also remove named subscriptions.

Within a subscription update block, you can remove all subscriptions from the subscriptions set with MutableSubscriptionSet.clear().

To remove all subscriptions from the subscription set, use removeAll() with no arguments.

To remove all subscriptions from the subscriptions set, execute a transaction on the subscriptions set. Call removeAll() on the MutableSubscriptionSet within the transaction.

To remove all subscriptions from the subscription set, use MutableSubscriptionSet.removeAll() with no arguments.

To remove all subscriptions from the subscription set, use removeAll() with no arguments.

To remove all subscriptions from the subscription set, use the removeAll method in a subscription update block.

To remove all subscriptions from the subscriptions set, execute a transaction on the subscriptions set. Call removeAll() on the MutableSubscriptionSet within the transaction.

// You can use .clear() inside a mutable_sync_subscription_set to clear all
// sync_subscription objects from the set
auto updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update(
[](realm::mutable_sync_subscription_set &subs) { subs.clear(); })
.get();
CHECK(updateSubscriptionSuccess == true);
CHECK(syncedRealm.subscriptions().size() == 0);

After you update subscriptions, call refresh() on the realm. This updates the database and outstanding objects managed by the database to point to the most recent data.

syncedRealm.refresh();
realm.Subscriptions.Update(() =>
{
// remove all subscriptions, including named subscriptions
realm.Subscriptions.RemoveAll(true);
});
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.clear();
});
realm.getSubscriptions().update(new SubscriptionSet.UpdateCallback() {
@Override
public void update(MutableSubscriptionSet subscriptions) {
subscriptions.removeAll();
}
});
realm.subscriptions.update((mutableSubs) => {
mutableSubs.removeAll();
});
// Remove all subscriptions
realm.subscriptions.update {
removeAll()
}
realm.subscriptions.update { subscriptions -> subscriptions.removeAll() }
let realm = try await getRealmAfterRemovingAllSubscriptions()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func getRealmAfterRemovingAllSubscriptions() async throws -> Realm {
let realm = try await Realm(configuration: flexSyncConfig)
let subscriptions = realm.subscriptions
try await subscriptions.update {
subscriptions.removeAll()
}
return realm
}
// The documentation does not currently have this code example in TypeScript.
// Please refer to the other languages or related pages for example code.

Adding several subscriptions with the .subscribe() and .unsubscribe() APIs described in the Subscribe to Queries section is less efficient than performing batch updates when you manually manage subscriptions. On every call to .subscribe(), the SDK opens a new update block. For better performance adding multiple subscriptions, use the subscriptions.update API described in the Manually Manage Subscriptions section.

Every write transaction for a subscription set has a performance cost. If you need to make multiple updates to a database object during a session, consider keeping edited objects in memory until all changes are complete. This improves sync performance by only writing the complete and updated object to your database instead of every change.

Adding an indexed queryable field to your App can improve performance for simple queries on data that is strongly partitioned. For example, an app where queries strongly map data to a device, store, or user, such as user_id == $0, “641374b03725038381d2e1fb”, is a good candidate for an indexed queryable field. However, an indexed queryable field has specific requirements for use in a query subscription:

  • The indexed queryable field must be used in every subscription query. It cannot be missing from the query.

  • The indexed queryable field must use an == or IN comparison against a constant at least once in the subscription query. For example, user_id == $0, "641374b03725038381d2e1fb" or store_id IN $0, {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 Device 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 example store_id IN {1,2,3} OR region=="Northeast" is invalid because it uses OR instead of AND. Similarly, store_id == 1 AND active_promotions < 5 OR num_employees < 10 is invalid because the AND 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 or truepredicate are invalid because they do not contain the indexed queryable field.

Device Sync does not support all RQL operators when creating your subscription queries. When you write the query subscription that determines which data to sync to the device, the server does not support these query operators. However, you can use all RQL operators to query the data set once it has synced to the client application.

Operator Type
Unsupported Operators
Aggregate Operators
@avg, @count, @max, @min, @sum
Query Suffixes
DISTINCT, SORT, LIMIT

Case insensitive queries ([c]) cannot use indexes effectively. As a result, case insensitive queries are not recommended, since they could lead to performance problems.

Device Sync only supports @count for array fields.

Device Sync supports querying lists using the IN operator.

You can query a list of constants to see if it contains the value of a queryable field:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

If a queryable field has an array value, you can query to see if it contains a constant value:

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

Warning

You cannot compare two lists with each other in a Device Sync query. Note that this is valid Realm Query Language syntax outside of Device Sync queries.

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

Device Sync does not support querying on properties in Embedded Objects or links. For example, obj1.field == "foo".

Back

Configure & Open a Synced Database

Next

Write to a Synced Database