Skip to main content

AppwriteRxDB Appwrite Replication

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.


Appwrite in 100 Seconds
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.
RxDatabase 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.



Client A
Client B
Client C

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 an .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:

Appwrite Database Tutorial
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 {
    getRxStorageLocalstorage
} from 'rxdb/plugins/storage-localstorage';
 
import { Client } from 'appwrite';
3

Create a Database with a Collection

const db = await createRxDatabase({
    name: 'mydb',
    storage: getRxStorageLocalstorage()
});
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://un5necb5yb5vju42me69r9mu.julianrbryant.com/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 functionality of the normal RxReplicationState.

Appwrite Sync

FAQ

Does Appwrite support multiple databases and subcollections?

Yes, Appwrite supports creating multiple top-level databases within a single project, which cleanly partition collections. However, Appwrite is a rigid NoSQL document store that does not support nested subcollections (unlike Firebase). When utilizing the RxDB Appwrite Replication plugin, your local RxDB schema must mirror this flat topology precisely, keeping all documents completely devoid of complex nested relationships.

What database driver does Appwrite use under the hood?

Appwrite uses MariaDB (a highly performant MySQL fork) as its core backing database driver. To offer developers a flat NoSQL experience, Appwrite abstracts the MariaDB relational complexity behind a unified Document API. This architectural mapping allows RxDB to replicate data effortlessly into Appwrite via standard REST endpoints without ever dealing with strict SQL table mappings or migrations.

Does Appwrite feature native real-time sync for offline apps?

Appwrite natively provides robust WebSocket subscriptions allowing clients to receive real-time document events while the network is active. However, Appwrite does not feature a built-in offline-first caching or background-sync engine. To achieve true offline capabilities, you must mount the RxDB Appwrite Replication plugin on the client. RxDB handles all local caching, queues offline writes securely, and automatically pushes local mutations to Appwrite when connectivity returns.

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.