CouchDB
02 / 02

Replication, Conflicts & Offline-First (PouchDB)

CouchDB: Replication, Conflicts & Offline-First

Multi-Master Replication

# Any instance -- including an offline device -- can accept writes
# independently. Bidirectional sync happens whenever connectivity allows.
curl -X POST http://localhost:5984/_replicate \
  -H 'Content-Type: application/json' \
  -d '{"source": "http://device-a:5984/mydb", "target": "http://server:5984/mydb"}'

# The changes feed is what replication (and change-driven apps) is
# built on -- a continuous stream of every document mutation in order
curl 'http://localhost:5984/mydb/_changes?feed=continuous&since=now'

Handling Conflicts

# Two disconnected replicas both edit the same document -> CouchDB
# does NOT silently pick a winner and discard the other. It keeps both
# revisions, deterministically serves one as the default "winner",
# and exposes the conflicting revision(s) for the app to resolve.
curl 'http://localhost:5984/mydb/doc1?conflicts=true'
# { "_id": "doc1", "_rev": "3-winner", "_conflicts": ["3-other"], ... }

# Application-level resolution: fetch the conflicting revision, merge
# using domain logic, then delete the losing revision explicitly --
# CouchDB itself has no way to know which edit "should" win.

PouchDB: Offline-First Sync

// PouchDB speaks CouchDB's replication protocol from inside a
// browser/mobile app -- store and query data fully offline, then
// sync bidirectionally whenever connectivity is available
import PouchDB from 'pouchdb';

const localDB = new PouchDB('my-local-db');
const remoteDB = new PouchDB('http://server:5984/mydb');

// Works fully offline -- writes stored locally immediately
await localDB.put({ _id: 'note1', text: 'Written offline' });

// Live, bidirectional sync -- reconnects and retries automatically
localDB.sync(remoteDB, { live: true, retry: true })
  .on('change', (info) => console.log('synced', info))
  .on('error', (err) => console.error('sync error', err));

Consistency & Cloudant

  • Eventual consistency: a replica that hasn't yet received a write can briefly serve stale data -- the trade-off for availability and partition tolerance.

  • Clustered mode's r/w quorum settings tune how many nodes must acknowledge a read/write before it's considered successful.

  • IBM Cloudant is a managed, distributed database-as-a-service built on and largely API-compatible with CouchDB -- a hosting path for the same data model and replication protocol.

  • Best fit: offline-first apps (field service, mobile) needing reliable local writes and conflict-aware sync once connectivity returns.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free