Understanding Durability & Write Safety in MongoDB

Durability is the “D” in the “ACID” properties (A – Atomicity, C – Consistency, I – Isolation), popularized by traditional relational database management systems (RDBMS). Durability is the guarantee that written data has been saved and will survive permanently. NoSQL databases like MongoDB give developers fine-grained control over the durability of their write calls. This enables developers to choose different durability, safety and performance models for different classes of data. However, this also places the burden on the developer to discern and understand the nuances of the different write safety options. In this post, we’ll look at the different options for write safety provided in the Java driver.

In MongoDB parlance, this is called “Write Concern”. Write concerns vary from “weak” to “strong”. Weak writes concerns can lead to higher throughput but provide less data safety and strong write concerns are vice versa.

The Java driver allows you to specify your write safety options using several telescoping constructors. Here is the constructor with all the options:

WriteConcern(int w, int wtimeout, boolean fsync, boolean j, boolean continueOnError)

As you can see, this constructor has a lot of options. In order to make it easier for developers, “Tags” are provided for common write concern values – Unacknowledged, Acknowledged, Journalled, Fsynced and Replica Acknowledged. Each tag maps to a certain invocation of the above constructor.

Unacknowledged MongoDB Mode

This is the “fire and forget” mode. The MongoDB driver does not attempt to acknowledge the receipt of write operations. For example, if your MongoDB service is down and you’re using this mode, all the errors are silently ignored and your data is lost. Obviously, you should only be using this mode for low-value data where write throughput is more important than loss of a certain amount of data. This mode can be specified as follows:

new WriteConcern(0) / WriteConcern.UNACKNOWLEDGED

Acknowledged MongoDB Mode

This is the default write mode for MongoDB. In this mode, the MongoDB driver attempts to acknowledge the receipt of write operations on the server, allowing the driver to catch any network errors, duplicate keys errors, etc. However, this does not guarantee that data is saved on the disk. If the MongoDB server crashes after acknowledging the write, but before committing it to disk, the data is lost. This mode can be specified as follows:

new WriteConcern(1) / WriteConcern.ACKNOWLEDGED

Journaled MongoDB Mode

In this mode, the MongoDB server acknowledges the write only after committing the data to the journal.  When using this mode, even if the server crashes on server restart, the data is reapplied from the journal. Obviously, journaling needs to be enabled for this to work. All production systems should have journaling enabled, and you can learn more about this in our post Should you enable MongoDB journaling?

In a replica set scenario, the journaling write concerns only apply to the primary. By default, the journal is committed to disk every 100ms. When you specify a write with the journaled option, the journal is committed to disk in 30ms. So, if you specify j:true for every write, your throughput will be a maximum of 1000/30 = 33.3 writes/sec. If you want better throughput, you’ll need to batch your updates and set j:true for the last update of the batch. This mode can be specified as follows:

WriteConcern( 1, 0, false, true ) / WriteConcern.JOURNALLED

Fsynced MongoDB Mode

In this mode, the MongoDB server acknowledges the write only after the write is written to disk. This mode can be specified as follows:

new WriteConcern(true) / WriteConcern.FSYNCED

Replica Acknowledged MongoDB Mode

The previous write safety modes apply only to a single server. When you run replica sets, you have the option of controlling how many replicas your write needs to be written before it is considered successful. For example, with a write concern of “w:2″, the write needs to be written to one primary and at least one secondary before it is considered successful. This reduces the throughput but gives you better safety. If you’re not aware of the number of replicas beforehand, you can use the WriteConcern.MAJORITY tag to ensure that the data is saved in the majority of the replicas. This is the safest option in MongoDB. If you’re going to use this option, also make sure to set the “wtimeout” value to indicate how long the command should wait before returning failure:

new WriteConcern(2)/ REPLICA_ACKNOWLEDGED
new Majority()/ WriteConcern.MAJORITY

The following tags have been deprecated (or plan to be) – ERRORS_IGNORED, NORMAL, SAFE, FSYNC_SAFE, JOURNAL_SAFE, REPLICAS_SAFE. Please use the newer options instead of these options. As always, if you have any comments or questions please reach out to us at support@scalegrid.io.


Dharshan is the founder of ScaleGrid.io (formerly MongoDirector.com). He is an experienced MongoDB developer and administrator. He can be reached for further comment at @dharshanrg


  • Boris Matos Morillo

    cleared all my doubts for “write concerns”, thank you very much

  • Dharshan

    Your welcome Boris!

  • Soumodip Sengupta

    This article was very helpful.Thankyou very much.

  • Michalis Argyriou

    On the last case that you describe “Replica acknowledged” please keep in mind that the replica secondary nodes will acknowledge any writes before updating the journal. Therefore even in this case if the primary node and the secondary nodes that were updated all fail during the ack response is returned to the client, the client may think that the write was successful but it wasn’t. I am not sure how the Java MongoDB driver will handle this …

  • yappo

    Write concerns and wtimeout are not supposed to be usesd for ‘better safety’. Check the documentation https://docs.mongodb.com/v3.2/reference/write-concern/#wtimeout

    wtimeout causes write operations to return with an error after the specified limit, even if the required write concern will eventually succeed. When these write operations return, MongoDB does not undo successful data modifications performed before the write concern exceeded the wtimeout time limit.

    This is made for lowering throughput only

  • astro

    Thanks, Dharshan. This is simple and concise explanation on writeConcern on MongoDB.

    I would like to add to this: 1. I have seen lot more number of writes/sec than the limit 33.33 writes/sec specified with Acknowledged & Journaled mode(with w=1, j tend to in-memory if not specified) with MongoDB.

    Same applies for the Replica Acknowledged MongoDB Mode with writeConcern as “majority” and j is unspecified( writeConcernMajorityJournalDefault=true by default)

    https://docs.mongodb.com/manual/reference/write-concern/#replica-sets

0 Shares
+1
Tweet
Share
Share
Pin