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.
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:
-
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.
-
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.
-
Conflict Handling: RxDB offers flexible conflict resolution strategies, making it simpler to handle concurrent edits across multiple users or devices.
-
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.
-
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.
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.
Set up an Appwrite Endpoint and Projectโ
Dockerโ
Ensure docker and docker-compose is installed and your version are up to date:
docker-compose -v
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
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
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:
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.
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.
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:
Install the Appwrite SDK and RxDB:โ
npm install appwrite rxdb
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';
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;
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');
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'
* ...
*/
});
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.