Continuous replication between CouchDB databases is surprisingly easy to set up, but its true power lies in understanding how CouchDB manages conflict resolution and failure scenarios automatically.
Let’s get this set up. Imagine you have a source-db on one CouchDB instance and a target-db on another. We want changes in source-db to automatically appear in target-db.
First, ensure you have two CouchDB instances running. For this example, let’s assume:
- Source:
http://admin:password@localhost:5984(database:source-db) - Target:
http://admin:password@remotehost:5984(database:target-db)
You can create the databases if they don’t exist:
curl -X PUT http://admin:password@localhost:5984/source-db
curl -X PUT http://admin:password@remotehost:5984/target-db
Now, we’ll create a replication document. This document lives inside the _replicator database on the CouchDB instance that will initiate the replication (in this case, the source-db instance). If _replicator doesn’t exist, CouchDB will create it for you on the fly when you add a replication document.
Here’s the JSON for our replication document:
{
"_id": "rep-source-to-target",
"source": "http://admin:password@localhost:5984/source-db",
"target": "http://admin:password@remotehost:5984/target-db",
"continuous": true,
"create_target": true
}
Let’s break this down:
"_id": A unique identifier for this replication job. You can name it anything descriptive."source": The URL of the database to replicate from."target": The URL of the database to replicate to."continuous": true: This is the magic flag. When set totrue, CouchDB will monitor the source database for changes and push them to the target indefinitely. If a document is updated in the source, the change will be replicated."create_target": true: If thetarget-dbdoesn’t exist on the target instance, CouchDB will create it for you. This is a handy convenience.
To add this replication document, use curl:
curl -X PUT http://admin:password@localhost:5984/_replicator/rep-source-to-target \
-H "Content-Type: application/json" \
-d '{
"_id": "rep-source-to-target",
"source": "http://admin:password@localhost:5984/source-db",
"target": "http://admin:password@remotehost:5984/target-db",
"continuous": true,
"create_target": true
}'
After you run this command, CouchDB will start the replication process. You can verify its status by checking the _replicator database on the source instance:
curl http://admin:password@localhost:5984/_replicator/rep-source-to-target
You’ll see fields like replication_id, doc_write_batch, docs_written, and status. If replication is active and healthy, the status will be triggered or running.
To see it in action, add a document to source-db:
curl -X POST http://admin:password@localhost:5984/source-db \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "city": "Wonderland"}'
Give it a few seconds, and then check target-db on the remote host:
curl http://admin:password@remotehost:5984/target-db/_all_docs?include_docs=true
You should see your new document, "Alice", appear.
CouchDB’s replication mechanism is designed for eventual consistency. This means that changes will propagate, but there might be a slight delay. Critically, CouchDB handles network interruptions and database downtime gracefully. If the target is unavailable, the replication job will simply retry until it succeeds. If the source is unavailable, the replication job will pause and resume when the source becomes available again.
The continuous setting means CouchDB uses a changes feed to monitor the source database. When a new document or revision is added to the source, CouchDB receives a notification via this feed and immediately processes it for replication to the target. This is far more efficient than polling.
One subtle but powerful aspect of CouchDB replication is how it handles conflicts. If the same document is modified independently on both the source and target (or on multiple sources replicating to the same target), CouchDB doesn’t just pick one. Instead, it creates a conflict. You’ll see a special _conflicts: true field on the document in the target database, and multiple winning revisions will be available. Your application then needs to be designed to read and resolve these conflicts, often by merging changes or picking a specific revision. This is a fundamental part of building distributed, fault-tolerant applications with CouchDB.
The next step is often setting up bidirectional replication, where changes in target-db also replicate back to source-db.