PouchDB Replicator Plugin
pouchdb-replicator is a PouchDB plugin that simulates the functionality of CouchDB's `_replicator` database daemon. Instead of initiating one-off or programmatic replication calls (e.g., `db.replicate()`), this plugin allows developers to define and manage persistent replication jobs declaratively by simply writing documents to a special `_replicator` database. This enables scenarios like continuous synchronization across application restarts and simplifies the management of complex replication topologies. The current stable version is 4.2.0, part of the pouchdb-server monorepo. It receives regular maintenance updates, focusing on bug fixes, dependency updates, and minor enhancements. Its key differentiator is providing a CouchDB-compatible declarative replication interface directly within PouchDB, making it ideal for applications requiring robust offline-first capabilities and seamless synchronization with CouchDB or other PouchDB instances.
Common errors
-
TypeError: PouchDB.plugin is not a function
cause The PouchDB library was either not imported, imported incorrectly (e.g., named import instead of default), or the `PouchDB.plugin()` method was called before the PouchDB object was properly initialized.fixEnsure `import PouchDB from 'pouchdb';` is at the top of your file and that `PouchDB.plugin(PouchDBReplicator);` is called after PouchDB is ready. -
Error: Database not found or permission denied
cause This error typically occurs during replication if the source or target database URL is incorrect, the database does not exist, or there are insufficient authentication credentials/permissions to access the remote database.fixDouble-check the `source` and `target` URLs/names in your `_replicator` document. If replicating to a remote CouchDB, ensure `auth` options (username, password) are correctly provided in the replication document, or the user has appropriate roles set up. -
Error: Document update conflict
cause When updating a replication document in the `_replicator` database, you must provide the correct `_rev` of the existing document. If the `_rev` is missing or stale, a conflict will occur.fixBefore updating a replication document, fetch its current `_rev` (e.g., via `replicatorDb.get(id)`), then include that `_rev` in your `put()` or `post()` call. Alternatively, use a PouchDB upsert plugin if available. -
TypeError: Cannot read properties of undefined (reading 'name') on 'source' or 'target'
cause If `source` or `target` are PouchDB database objects instead of names/URLs, this error suggests that the PouchDB instance itself (e.g., `localDb` in the quickstart) was not properly initialized or is `undefined` when its `.name` property is accessed.fixEnsure that `new PouchDB('db_name')` calls are awaited or handled as promises, and that the resulting PouchDB objects are valid before being used in the replication document.
Warnings
- breaking Version 4.0.0 was the first release built from a complete monorepo, changing internal structures and dependencies. It also addressed a security issue. While the impact on direct API usage for `pouchdb-replicator` itself might be minimal, users upgrading from pre-4.0.0 versions should be aware of potential broader ecosystem changes within `pouchdb-server`.
- breaking Version 2.0.0 introduced breaking changes that correspond to `express-pouchdb` 2.0.0, specifically impacting database name encoding for adapters that store files. If database names contained '/' characters, existing databases might not be found. Additionally, version 2.0.0 onward uses prefixed replication fields (`_replication_state` instead of `replication_state`).
- gotcha A potential `EventEmitter` memory leak issue was fixed in version 4.1.0 (#233). Applications with many active replications or frequent replication job changes might have experienced memory consumption growth over time in earlier versions.
- gotcha Version 4.2.0 fixed an issue where `.info` errors were being swallowed, leading to silent failures or missed diagnostic information during replication.
- breaking PouchDB (and by extension its plugins like `pouchdb-replicator`) has evolved towards ESM. While older versions might support CommonJS, modern PouchDB usage (especially with recent versions like v7+) strongly encourages ESM for better compatibility and tree-shaking.
- deprecated The broader PouchDB ecosystem has seen significant shifts, with some perspectives considering PouchDB legacy for high-performance use cases due to revision handling overhead and bundle size. While `pouchdb-replicator` remains functional, consider the long-term architectural implications if performance or strict modern database standards are critical.
Install
-
npm install pouchdb-replicator -
yarn add pouchdb-replicator -
pnpm add pouchdb-replicator
Imports
- PouchDBReplicator
const PouchDB = require('pouchdb'); const PouchDBReplicator = require('pouchdb-replicator'); // CommonJS for older Nodeimport PouchDB from 'pouchdb'; import PouchDBReplicator from 'pouchdb-replicator';
- PouchDB.plugin
new PouchDBReplicator(); // or just importing without registering
PouchDB.plugin(PouchDBReplicator);
- PouchDB
import { PouchDB } from 'pouchdb'; // or not importing it at allimport PouchDB from 'pouchdb';
Quickstart
import PouchDB from 'pouchdb';
import PouchDBReplicator from 'pouchdb-replicator';
// Register the PouchDB Replicator plugin
PouchDB.plugin(PouchDBReplicator);
async function setupPersistentReplication() {
// Initialize a local PouchDB database
const localDb = new PouchDB('my_local_db');
// Define a remote PouchDB/CouchDB instance URL
const remoteDbUrl = 'http://localhost:5984/my_remote_db'; // Ensure CouchDB is running or this is a valid PouchDB instance
// The special _replicator database to manage replication jobs
const replicatorDb = new PouchDB('_replicator');
try {
// Create a continuous replication job by posting a document to _replicator
// This will instruct PouchDB-Replicator to start and manage the replication.
const replicationJob = {
_id: 'my-first-continuous-sync',
source: localDb.name, // Source database: 'my_local_db'
target: remoteDbUrl, // Target database: 'http://localhost:5984/my_remote_db'
continuous: true, // Keep replication running continuously
live: true, // Also track future changes (often implied by continuous)
retry: true, // Automatically retry on failure
// For authenticated replication to a remote CouchDB:
// auth: {
// username: process.env.COUCHDB_USERNAME ?? 'admin',
// password: process.env.COUCHDB_PASSWORD ?? 'password'
// }
};
const response = await replicatorDb.put(replicationJob);
console.log('Replication job started successfully:', response);
// To stop or update the replication, you would modify or delete this document from _replicator
// e.g., await replicatorDb.remove(response.id, response.rev);
} catch (error: any) {
console.error('Failed to set up replication job:', error);
// Handle common errors like network issues, authentication failures, etc.
}
}
setupPersistentReplication();