Configuring The Realm To Be Opened

Before you can open a synced Realm, you must first provide a configuration for it. This process is similar to configuring local Realms, such as defining the local path on disk, but synced Realms have specific requirements and not all configuration options apply.

The Default Synced Realm

The easiest way to get started with Realm Platform is to use the default synchronized Realm. With Realm Platform - Cloud each cloud instance will have a single default Realm. For Self-Hosted each server installation will include a single default Realm.

For most apps, you can include all of your application data within the default synchronized Realm. Realm Platform supports query-based sync, so that you can control what data from the default synced Realm is synchronized to the client application.

In addition, to you application data, the server will also include other internal classes used in its management and the master list of authenticated users, represented by the __User class. The internal data is managed through fine-grained access control.

The purpose of the default synchronized Realm is to simplify getting started and allow your application data to link into the master list of authenticated users.

Swift
Objective-C
Java
Javascript
.Net

The default synced Realm is provided via an automatic SyncConfiguration that can be accessed from the logged in SyncUser.

For example, to log in, then asynchronously open the default synced Realm:

SyncUser.logIn(with: credentials, server: serverURL) { user, error in
if let user = user {
Realm.Configuration.defaultConfiguration = user.configuration()
Realm.asyncOpen() { realm in
// ...
}
}
}

The default synced Realm is provided via an automatic RLMSyncConfiguration that can be accessed from the logged in RLMSyncUser.

For example, to log in, then asynchronously open the default synced Realm:

[RLMSyncUser logInWithCredentials:credentials
authServerURL:serverURL
onCompletion:^(RLMSyncUser *user, NSError *error) {
if (user) {
RLMRealmConfiguration *config = [user configuration];
[RLMRealm asyncOpenWithConfiguration:config
callbackQueue:dispatch_get_main_queue()
callback:^(RLMRealm *realm, NSError *error) {
if (realm) {
// ...
}
}];
}
}];

The default synced Realm is provided via an automatic SyncConfiguration that can be accessed from the logged in SyncUser.

For example, to log in and open the default synced Realm:

SyncCredentials credentials = getCredentials();
String url = getUrl();
SyncUser.login(credentials, url, new SyncUser.Callback<SyncUser>() {
@Override
public void onSuccess(SyncUser user) {
SyncConfiguration config = user.getDefaultConfiguration();
Realm realm = Realm.getInstance(config);
// Use Realm
}
@Override
public void onError(ObjectServerError error) {
// Handle error
}
});

The default synced Realm is provided via the default configuration which can be accessed from the logged in Realm.Sync.User.

When using query-based sync with Javascript, you are required to pass in a schema for your Realm.

For example, to log in and open the default synced Realm:

Realm.Sync.User.login(server, username, password)
.then((user) => {
let config = user.createConfiguration();
config.schema = [Schema];
Realm.open(config).then((realm) => {
// ...
});
})

The default synced Realm is provided via an automatic QueryBasedSyncConfiguration, which will use the current logged in user from User.Current and the server URL used to authenticate.

For example, to log in, then asynchronously open the default synced Realm with the current user:

var user = await User.LoginAsync(credentials, serverUrl);
RealmConfiguration.DefaultConfiguration = new QueryBasedSyncConfiguration();
var realm = await Realm.GetInstanceAsync();

If you are working with multiple users, you can pass in the specific user as well:

var user = await User.LoginAsync(credentials, serverUrl);
RealmConfiguration.DefaultConfiguration = new QueryBasedSyncConfiguration(user: user);
var realm = await Realm.GetInstanceAsync();

Manually Configuring Synced Realms

If your application is using multiple Realms, you can manually configure a synced Realm by supplying:

  1. An authenticated user

  2. The Realm URL

The Realm URL uses a specific scheme: realm:// for non-secure connections and realms:// for secure connections.

For more details, see the Understanding Realm URLs and Paths section below.

To obtain an authenticated user, you must login via any of the supported authentication providers. If you are unfamiliar, see the Working With Users section.

Swift
Objective-C
Java
Javascript
.Net

Realms on the Realm Object Server are using the same Realm.Configuration used to create standalone Realms, but with the syncConfiguration property on their Realm.Configuration set to a SyncConfiguration value. Synchronized realms are located by URLs.

// Create the configuration
let syncServerURL = URL(string: "realms://myinstance.cloud.realm.io/~/userRealm")!
let config = user.configuration(realmURL: syncServerURL);
// Open the remote Realm
let realm = try! Realm(configuration: config)
// Any changes made to this Realm will be synced across all devices!

The configuration values for a synced Realm cannot have an inMemoryIdentifier or fileURL configured. Setting either property will automatically nil out the syncConfiguration property (and vice-versa). The framework is responsible for managing how synchronized Realms are cached or stored on disk.

Realms on the Realm Object Server are using the same RLMRealmConfiguration that are used to create standalone Realms, but with the syncConfiguration property on their RLMRealmConfiguration set to a RLMSyncConfiguration value. Synchronized realms are located by URLs.

RLMSyncUser *user = [RLMSyncUser currentUser];
// Create the configuration
NSURL *syncServerURL = [NSURL URLWithString: @"realms://myinstance.cloud.realm.io/~/userRealm"];
RLMRealmConfiguration *config = [user configurationWithUrl:syncServerURL];
// Open the remote Realm
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
// Any changes made to this Realm will be synced across all devices!

The configuration values for a synced Realm cannot have an inMemoryIdentifier or fileURL configured. Setting either property will automatically nil out the syncConfiguration property (and vice-versa). The framework is responsible for managing how synchronized Realms are cached or stored on disk.

Realms on the Realm Object Server are created using a subclass of the normal RealmConfiguration used to create standalone Realms. This class is named SyncConfiguration and uses the same builder pattern known from normal Realms. Specifically it requires an User and an URL.

// Create the configuration
SyncUser user = SyncUser.currentUser();
String url = "realms://myinstance.cloud.realm.io/~/userRealm";
SyncConfiguration config = user.createConfiguration(url).build();
// Open the remote Realm
Realm realm = Realm.getInstance(config);
// Any changes made to this Realm will be synced across all devices!

You open a synchronized Realm the same say as you open any other Realm. The configuration can be extended with a sync property if you need to configure the synchronization. The optional properties of sync include:

  • error - a callback for error handling/reporting

  • validate_ssl - indicating if SSL certificates must be validated

  • ssl_trust_certificate_path - a path where to find trusted SSL certificates

  • url - if no url is provided the url to the default Realm will be used.

The error handling is set up by registering a callback (error) as part of the configuration:

const user = Realm.Sync.User.current;
user.createConfiguration({
sync: { url: "realms://myinstance.cloud.realm.io/~/userRealm",
error: err => console.log(err)
},
schema: // ...
});
var realm = new Realm(config);

For standalone Realms, RealmConfiguration is used to configure the options for a Realm. Synchronized Realms on the other hand, are configured using extended configuration classes called QueryBasedSyncConfiguration or FullSyncConfiguration.

The configuration ties together an authenticated user and a sync server URL. The sync server URL may contain the tilde character (“~”) which will be transparently expanded to represent the user’s unique identifier. This scheme easily allows you to write your app to cater to its individual users. The location on disk for shared Realms is managed by the framework, but can be overridden if desired.

var user = User.Current;
var serverURL = new Uri("/default", UriKind.Relative);
var configuration = new QueryBasedSyncConfiguration(serverURL, user);
var realm = Realm.GetInstance(configuration);

Fully synchronized Realms

Synchronized Realms come in two flavors: Query-based and Fully synchronized. You can read more about the differences here.

When connecting to a synchronized Realm it is important that the configuration matches the type of the server Realm, otherwise the connection will fail. Query-based Realms are the default if not otherwise specified.

If you intend to use fully synchronized Realms, you can do so by adjusting a parameter on the sync configuration:

Swift
Objective-C
Java
Javascript
.Net
user.configuration(realmURL: realmURL, fullSynchronization: true)
RLMRealmConfiguration *config = [RLMRealmConfiguration configurationWithUrl:realmURL fullSynchronization:YES];
SyncConfiguration config = user.createConfiguration(getUrl())
.fullSynchronization()
.build();
const config = {
sync: { url: realmUrl,
fullSynchronization: true,
},
// ...
};
var config = new FullSyncConfiguration(realmUrl, user);

Synchronously Opening A Realm

To access a Realm immediately in your application, you can open a Realm "synchronously." This might be confusing since "synchronous" in this case means the API will return the Realm immediately. However, given that we are opening a synchronized Realm, the first time you open the Realm there will always be no data in it. In the background, the Realm will establish a sync session and start downloading any existing data from the server. You can attach a progress listener to track the download activity or you can subscribe to notifications to get events when the data changes.

This API is recommended when your want the user experience to not be blocked while the data is downloaded, such as displaying partial data to the user in the process.

Swift
Objective-C
Java
Javascript
.Net
// Create the configuration
let syncServerURL = URL(string: "realms://myinstance.cloud.realm.io/~/userRealm")!
let config = user.configuration(realmURL: syncServerURL))
// Open the remote Realm
let realm = try! Realm(configuration: config)
// Any changes made to this Realm will be synced across all devices!
RLMSyncUser *user = [RLMSyncUser currentUser];
// Create the configuration
NSURL *syncServerURL = [NSURL URLWithString: @"realms://myinstance.cloud.realm.io/~/userRealm"];
RLMRealmConfiguration *config = [user configurationWithUrl:syncServerURL];
// Open the remote Realm
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
// Any changes made to this Realm will be synced across all devices!
// Create the configuration
SyncUser user = SyncUser.currentUser();
String url = "realms://myinstance.cloud.realm.io/~/userRealm";
SyncConfiguration config = user.createConfiguration(url).build();
// Open the remote Realm
Realm realm = Realm.getInstance(config);
// Any changes made to this Realm will be synced across all devices!
const user = Realm.Sync.User.current;
const config = user.createConfiguration({
sync: { url: "realms://myinstance.cloud.realm.io/~/userRealm",
error: err => console.log(err)
},
schema: // ...
});
var realm = new Realm(config);
var user = User.Current;
var serverURL = new Uri("/default", UriKind.Relative);
var configuration = new QueryBasedSyncConfiguration(serverURL, user);
var realm = Realm.GetInstance(configuration);

If a Realm has read-only file-level permissions, then you must asynchronously open the Realm as described in Asynchronously Opening A Realm. Opening a file-level read-only Realm without the asynchronous API will cause an error.

This behavior does not apply to partially synced Realms that use the finer-grainer access controls.

Asynchronously Opening A Realm

In some cases, you might not want to open a Realm until it has all remote data available. For example, if you want to show the users a list of all available ZIP codes. Asynchronously opening a Realm uses an API that has a callback which will not return the Realm until it is fully downloaded.

Swift
Objective-C
Java
Javascript
.Net
let config = user.configuration(realmURL: realmURL))
Realm.asyncOpen(configuration: config) { realm, error in
if let realm = realm {
// Realm successfully opened, with all remote data available
} else if let error = error {
// Handle error that occurred while opening or downloading the contents of the Realm
}
}
RLMRealmConfiguration *config = [user configurationWithUrl:realmURL];
[RLMRealm asyncOpenWithConfiguration:config
callbackQueue:dispatch_get_main_queue()
callback:^(RLMRealm *realm, NSError *error) {
if (realm) {
// Realm successfully opened, with all remote data available
} else if (error) {
// Handle error that occurred while opening or downloading the contents of the Realm
}
}
// Create the configuration specifying that the Realm cannot be opened
// the first time until server data has been downloaded. This only
// blocks it from being opened the first time. After that the Realm can
// be opened immediately.
SyncConfiguration config = user.createConfiguration(url)
.waitForInitialRemoteData();
.build();
// Open the remote Realm
Realm realm = Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
// Realm is ready
}
@Override
public void onError(Throwable exception) {
// Handle error
}
});
const user = Realm.Sync.User.current;
const config = user.createConfiguration({
sync: { url: "realm://localhost:9080/~/userRealm",
error: err => console.log(err)
},
schema: // ...
});
Realm.open(config)
.then(realm => {
// ...use the realm instance here
})
.catch(error => {
// Handle the error here if something went wrong
});
var serverURL = new Uri("/default", UriKind.Relative);
var config = new QueryBasedSyncConfiguration(serverURL, user);
try
{
var realm = await Realm.GetInstanceAsync(config);
// Realm successfully opened, with all remote data available
}
catch (Exception ex)
{
// Handle error that occurred while opening or downloading the contents of the Realm
}

Understanding Realm URLs and Paths

Synchronized Realms exists as resources tied to a specific URL path. If you are manually opening synchronized Realms and/or splitting your data up between multiple Realms then this is important to understand.

If you are using the default synced Realm, you typically don't need to worry about this, as the Realm URL is automatically configured for you at the path: /default

Realm Scheme

The URLs for synchronized Realms use a dedicated scheme. The underlying networking is not using standard HTTP, but instead Websockets. We chose not to use the Websockets scheme ws/wss because we utilize a custom protocol and wanted to emphasize the distinction.

For unsecured synchronized connections, the scheme is realm://.

For secured synchronized connections , the schema is realms://.

Take care not to mix up the http/https scheme used in the authentication URL when logging in a user.

Path Restrictions

The Realm Object Server includes a path-level permission system. By default, it restricts the creation of Realms to scoped paths for the user. For example, if a user's ID is 12345 then this user can only create Realms at the path /12345/myRealm.

This restriction is not enforced for admin users. As a result, if you want to create a global Realm at the base path, /globalRealm the creation of the Realm must be done by an admin user.

You can learn more about the details of path-level permissions in its dedicated section, including how to adjust these permissions to share a Realm:

~ Shorthand

When working with Realm paths you might quickly realize that it is time-consuming to keep track of the userId in a scoped-path. To simplify, Realm paths accept as shorthand the use of the tilde ~ character in exchange for the userId. For example, if you open a Realm with a user whose userId is 12345, you can use either of these URL paths to open the same Realm:

"realms://myinstance.cloud.realm.io/~/myRealm"
"realms://myinstance.cloud.realm.io/12345/myRealm"

Not what you were looking for? Leave Feedback