Skip to main content

RxDB Appwrite Replication (Pre Alpha)

This replication plugin allows you to synchronize documents between RxDB and an Appwrite server. It supports both push and pull replication, live updates via Appwrite's real-time subscriptions, offline-capability and conflict resolution.


2:35
Appwrite in 100 Seconds

Why you should use RxDB with Appwrite?โ€‹

Appwrite is a secure, open-source backend server that simplifies backend tasks like user authentication, storage, database management, and real-time APIs.
RxDB is a reactive database for the frontend that offers offline-first capabilities and rich client-side data handling.

Combining the two provides several benefits:

  1. Offline-First: RxDB keeps all data locally, so your application remains fully functional even when the network is unavailable. When connectivity returns, the RxDB โ†” Appwrite replication automatically resolves and synchronizes changes.

  2. Real-Time Sync: With Appwriteโ€™s real-time subscriptions and RxDBโ€™s live replication, you can build collaborative features that update across all clients instantaneously.

  3. Conflict Handling: RxDB offers flexible conflict resolution strategies, making it simpler to handle concurrent edits across multiple users or devices.

  4. Scalable & Secure: Appwrite is built to handle production loads with granular access controls, while RxDB easily scales across various storage backends on the client side.

  5. Simplicity & Modularity: RxDBโ€™s plugin-based architecture, combined with Appwriteโ€™s Cloud offering makes it one of the easiest way to build local-first realtime apps that scale.



Appwrite Sync

Preparing the Appwrite Serverโ€‹

You can either use the appwrite cloud or self-host the Appwrite server. In this tutorial we use the Cloud which is recommended for beginners because it is way easier to set up. You can later decide to self-host if needed.

1.

Set up an Appwrite Endpoint and Projectโ€‹

1.
Dockerโ€‹

Ensure docker and docker-compose is installed and your version are up to date:

docker-compose -v
2.
Run the installation scriptโ€‹

The installation script runs inside of a docker container. It will create a docker-compose file and and .env file.

docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:1.6.1
3.
Start/Stopโ€‹

After the installation is done, you can manually stop and start the appwrite instance with docker compose:

# stop
docker-compose down

# start
docker-compose up
2.

Create an Appwrite Database and Collectionโ€‹

After creating an Appwrite project you have to create an Appwrite Database and a collection, you can either do this in code with the node-appwrite SDK or in the Appwrite Console as shown in this video:

9:47
Appwrite Database Tutorial

3.

Add your documents attributesโ€‹

In the appwrite collection, create all attributes of your documents. You have to define all the fields that your document in your RxDB schema knows about. Notice that Appwrite does not allow for nested attributes. So when you use RxDB with Appwrite, you should also not have nested attributes in your RxDB schema.

4.

Add a deleted attributeโ€‹

Appwrite (natively) hard-deletes documents. But for offline-handling RxDB needs soft-deleted documents on the server so that the deletion state can be replicated with other clients.

In RxDB, _deleted indicates that a document is removed locally and you need a similar field in your Appwrite collection on the Server: You must define a deletedField with any name to mark documents as "deleted" in the remote collection. Mostly you would use a boolean field named deleted (set it to required). The plugin will treat any document with { [deletedField]: true } as deleted and replicate that state to local RxDB.

5.

Set the Permission on the Appwrite Collectionโ€‹

Appwrite uses permissions to control data access on the collection level. Make sure that in the Console at Collection -> Settings -> Permissions you have set the permission according to what you want to allow your clients to do. For testing, just enable all of them (Create, Read, Update and Delete).

Setting up the RxDB - Appwrite Replicationโ€‹

Now that we have set up the Appwrite server, we can go to the client side code and set up RxDB and the replication:

1.

Install the Appwrite SDK and RxDB:โ€‹

npm install appwrite rxdb
2.

Import the Appwrite SDK and RxDBโ€‹

import {
replicateAppwrite
} from 'rxdb/plugins/replication-appwrite';
import {
createRxDatabase,
addRxPlugin,
RxCollection
} from 'rxdb/plugins/core';
import {
getRxStorageDexie
} from 'rxdb/plugins/storage-dexie';

import { Client } from 'appwrite';
3.

Create a Database with a Collectionโ€‹

const db = await createRxDatabase({
name: 'mydb',
storage: getRxStorageDexie()
});
const mySchema = {
title: 'my schema',
version: 0,
primaryKey: 'id',
type: 'object',
properties: {
id: {
type: 'string',
maxLength: 100
},
name: {
type: 'string'
}
},
required: ['id', 'name']
};
await db.addCollections({
humans: {
schema: mySchema
}
});
const collection = db.humans;
4.

Configure the Appwrite Clientโ€‹

const client = new Client();
client.setEndpoint('https://cloud.appwrite.io/v1');
client.setEndpointRealtime('https://cloud.appwrite.io/v1');
client.setProject('YOUR_APPWRITE_PROJECT_ID');
5.

Start the Replicationโ€‹

const replicationState = replicateAppwrite({
replicationIdentifier: 'my-appwrite-replication',
client,
databaseId: 'YOUR_APPWRITE_DATABASE_ID',
collectionId: 'YOUR_APPWRITE_COLLECTION_ID',
deletedField: 'deleted', // Field that represents deletion in Appwrite
collection,
pull: {
batchSize: 10,
},
push: {
batchSize: 10
},
/*
* ...
* You can set all other options for RxDB replication states
* like 'live' or 'retryTime'
* ...
*/
});
6.

Do other things with the replication stateโ€‹

The RxAppwriteReplicationState which is returned from replicateAppwrite() allows you to run all functionaliy of the normal RxReplicationState.

Limitations of the Appwrite Replication Pluginโ€‹

  • Appwrite primary keys only allow for the characters a-z, A-Z, 0-9, and underscore _ (They cannot start with a leading underscore). Also the primary key has a max length of 36 characters.
  • The Appwrite replication only works on browsers. This is because the Appwrite SDK does not support subscriptions in Node.js.
  • Appwrite does not allow for bulk write operations so on push one HTTP request will be made per document. Reads run in bulk so this is mostly not a problem.
  • Appwrite does not allow for transactions or "update-if" calls which can lead to overwriting documents instead of properly handling conflicts when multiple clients edit the same document in parallel. This is not a problem for inserts because "insert-if-not" calls are made.
  • Nested attributes in Appwrite collections are only possible via experimental relationship attributes, and compatibility with RxDB is not tested. Users opting to use these experimental relationship attributes with RxDB do so at their own risk.
โœ•