Conflicts occur in Cloudant and Apache CouchDB databases when the same document is written to in different ways in separate copies of the database. This can occur when there is:

As this three part blog series discusses, conflicts are not an error condition - they are symptom of the database ensuring that you don’t lose data. Sometimes conflicts occur by accident - perhaps some automated process that updates the database happening to run more frequently than normal. Ideally your code would detect the conflicts and have an algorithm to fix them.

conflict

If left unchecked, conflicted documents can be a headache for the performance of the database. In some cases, documents can have hundreds or thousands of conflicted revisions. As the database has to keep the bodies of the conflicted documents, they eat up your storage quota and make the revision tree costly to navigate.

Detecting conflicts

You can see if a document is conflicted by fetching the document with ?conflicts=true appended to the URL:

curl http://localhost:5984/mydb/mydoc?conflicts=true
{"_id":"mydoc","_rev":"1-99","a":98,"_conflicts":["1-98","1-97","1-96","1-95"]}

In the above case, the document has a winning revision 1-99 and four other revisions that are non-winning. If I delete the conflicting revisions the document returns to its normal state.

curl -X DELETE http://localhost:5984/mydb/mydoc?rev=1-98
curl -X DELETE http://localhost:5984/mydb/mydoc?rev=1-97
curl -X DELETE http://localhost:5984/mydb/mydoc?rev=1-96
curl -X DELETE http://localhost:5984/mydb/mydoc?rev=1-95

I don’t have to delete the conflicts. I could have chosen to retain revision 1-96 - simply deleting the winning revision and the other conflicts would promote 1-96 to be the winner.

This is simple enough when there are only a handful of conflicts but if there are hundreds or thousands, some tooling would help.

Introducing couchdeconflict

I wrote a simple command-line utility to help clean up CouchDB/Cloudant documents that have become conflicted. It is installed with

npm install -g couchdeconflict

and run by specifying the URL of the document to work on:

> couchdeconflict -u http://localhost:5984/mydb/mydoc
options: {"url":"http://localhost:5984/mydb/mydoc","keep":null,"batch":100}
Fetching document
217 conflicts
  [==================================================] 100% 217/217           
217 conflicts deleted

By default, the pre-existing winning revision is retained and the conflicted revisions are deleted. You can nominate a new winning revision with the --keep parameter:

> couchdeconflict --url http://localhost:5984/mydb/mydoc  --keep 1-111
couchdeconflict
---------------
options: {"url":"http://###:###@localhost:5984/mydb/mydoc","keep":"1-111","batch":100}
Fetching document
217 conflicts
Keeping revision 1-111
  [==================================================] 100% 217/217           
217 conflicts deleted

If you’re worried about what this utility is going to do to your database, you can do a dummy run with the --dryrun parameter:

> couchdeconflict --url http://localhost:5984/mydb/mydoc  --keep 1-111 --dryrun

Further reading

If you want to explore this subject further, here’s some links: