Skip to main content

Google DriveReplication with Google Drive

The replication-google-drive plugin allows you to replicate your client-side RxDB database to a folder in the user's Google Drive. This enables cross-device sync for single users without requiring any backend server.

Overview​

The replication uses the Google Drive API v3 and v2.

  • Offline-First: Users can work offline. Changes are synced when they go online.
  • No Backend Required: You don't need to host your own database server.
  • Cross-Device: Users can access their data from multiple devices by signing into the same Google account.
  • Realtime Sync: Uses WebRTC for peer-to-peer signaling to achieve near real-time updates. Uses the same google-drive folder instead of a signaling-server.
Beta Feature(available since version 17.0.0)
This feature is in beta and may have breaking changes without a major RxDB version release.

Usage​

1

Enable Google Drive API​

You need to enable the Google Drive API in the Google Cloud Console and create credentials (OAuth 2.0 Client ID) for your application.

2

Authenticate the User​

Your application must handle the OAuth flow to get an accessToken from Google. You can use libraries like @react-oauth/google or the Google Identity Services SDK.

3

Start Replication​

Once you have the accessToken, you can start the replication.

import { replicateGoogleDrive } from 'rxdb/plugins/replication-google-drive';
 
const replicationState = await replicateGoogleDrive({
    replicationIdentifier: 'my-app-drive-sync',
    collection: myRxCollection, // RxCollection
    googleDrive: {
        oauthClientId: 'YOUR_GOOGLE_CLIENT_ID',
        authToken: 'USER_ACCESS_TOKEN',
        folderPath: 'my-app-data/user-1'
    },
    live: true,
    pull: {
        batchSize: 60,
        modifier: doc => doc // (optional) modify invalid data
    },
    push: {
        batchSize: 60,
        modifier: doc => doc // (optional) modify before sending
    }
});
 
// Observe replication states
replicationState.error$.subscribe(err => {
    console.error('Replication error:', err);
});
 
replicationState.awaitInitialReplication().then(() => {
    console.log('Initial replication done');
});

Signaling & WebRTC​

Google Drive does not provide real-time events for file changes. If a user changes data on User Device A, User Device B would not know about it until it periodically polls the Drive API. To achieve real-time updates, this plugin uses WebRTC to signal changes between connected devices.

  1. Devices create "signal files" in a signaling subfolder on Google Drive.
  2. Other devices detect these files, read the WebRTC connection data, and establish a direct P2P connection with each other.
  3. When a device makes a write, it sends a "RESYNC" signal via WebRTC to all connected peers to notify them about the change.

Polyfill for Node.js​

WebRTC is native in browsers but requires a polyfill in Node.js. Use createSimplePeerWrtc() to wrap the polyfill for compatibility with simple-peer:

import nodeDatachannelPolyfill from 'node-datachannel/polyfill';
import { createSimplePeerWrtc } from 'rxdb/plugins/replication-webrtc';
// ...
const replicationState = await replicateGoogleDrive({
    // ...
    signalingOptions: {
        wrtc: createSimplePeerWrtc(nodeDatachannelPolyfill)
    }
});

Options​

googleDrive​

  • oauthClientId string: The OAuth 2.0 Client ID of your application.
  • authToken string: The valid access token associated with the user.
  • folderPath string: The path to the folder in Google Drive where data should be stored.
    • The plugin will ensure this folder exists.
    • For the default drive space it must not be the root folder.
    • For the appDataFolder space it is optional and interpreted relative to the appDataFolder root.
    • It creates subfolders docs (for data) and signaling (for WebRTC).
  • space 'drive' | 'appDataFolder' (optional): Defaults to 'drive'. See the section below.
  • apiEndpoint string (optional): Defaults to https://www.googleapis.com. Useful for mocking or proxies.
  • transactionTimeout number (optional): Default 10000 (10s). The plugin uses a transaction file in Drive to ensure data integrity during writes. This is the timeout after which a lock is considered stale.

Using the appDataFolder​

By default the plugin stores data in the user visible "My Drive". Set space: 'appDataFolder' to store data in Google Drive's hidden, per-application data folder instead. This is useful on Android and other clients where you want app state synced across the user's devices without cluttering their Drive UI.

const replicationState = await replicateGoogleDrive({
    replicationIdentifier: 'my-app-drive-sync',
    collection: myRxCollection,
    googleDrive: {
        oauthClientId: 'YOUR_GOOGLE_CLIENT_ID',
        authToken: 'USER_ACCESS_TOKEN',
        space: 'appDataFolder'
        // folderPath is optional here
    },
    live: true,
    pull: {},
    push: {}
});

When using appDataFolder:

  • Request the https://www.googleapis.com/auth/drive.appdata OAuth scope when you authenticate the user. The regular Drive scopes do not grant access to this space.
  • The data is hidden from the user's Drive UI and cannot be browsed manually.
  • The folder is isolated per OAuth client id. A debug build and a release build with different client ids will not see each other's data.
  • folderPath is optional. If omitted, the docs and signaling subfolders are created directly in the appDataFolder root.

attachments​

Controls whether binary attachment data is replicated along with documents.

  • Default: enabled automatically when the collection schema has attachments: {} defined.
  • Set attachments: false to disable attachment replication (only document fields are synced).
const replicationState = await replicateGoogleDrive({
    // ...
    attachments: false, // disable attachment replication
    pull: {},
    push: {}
});

When attachment replication is enabled, attachment binary data is encoded as base64 and stored in a separate _attachments_data field inside the document's JSON file on Drive. The standard _attachments field only contains metadata stubs (digest, length, type). On pull, the base64 data is decoded back to Blob instances and written to local storage.

pull & push​

Standard RxDB Replication Options for batch size, modifiers, etc.

Technical Details​

File Mapping​

  • Each RxDB document corresponds to one JSON file in the docs subfolder.
  • The filename is [primaryKey].json.
  • This simple mapping makes it easy to inspect or backup data manually.

Checkpointing​

  • The replication relies on the modifiedTime of files in Google Drive.

Conflict Resolution​

  • Conflicts are handled using the standard RxDB conflict handling strategies.
  • The plugin assumes a master-slave replication pattern where the client (RxDB) merges changes.
  • If the transaction file is locked by another device, the write retries until the lock is released or times out.

Limitations​

  • Rate Limits: Google Drive API has strict rate limits. The plugin attempts to handle 429 errors with exponential backoff, but heavy concurrent writes might hit these limits.
  • Latency: Changes take time to propagate and appear in listings (eventual consistency), which the plugin handles internally.
  • Signaling Delay: The initial WebRTC handshake requires writing and reading files from Drive, which can take a few seconds. Once connected, signaling is instant.

Testing​

For testing, it is recommended to use google-drive-mock. It simulates the Google Drive API so you can run tests without real credentials.

FAQ​

What are the Google Drive API request limits?

Google Drive API rate limiting is based on quota units, not a flat request count. According to the official Google Drive API usage limits documentation, the default limits are:

  • 1,000,000 quota units per minute per project
  • 325,000 quota units per minute per user (within a project)

So the HTTP requests/minute depends on the endpoint cost:

  • If an endpoint costs 1 quota unit/request, the theoretical maximum is 1,000,000 req/min/project and 325,000 req/min/user.
  • If an endpoint costs 100 quota units/request (for example files.list in many setups), that is about 10,000 req/min/project and 3,250 req/min/user.

When limits are exceeded, Google can return 403 (User rate limit exceeded) or 429 (Rate limit exceeded) responses.

The replication plugin already retries with exponential backoff, but for high-traffic apps you should monitor quota usage and tune your sync frequency/batch sizes.