title: Preventing database-related race conditions in Node.js
body: <h2>Overview</h2>
  
  <p>I am attempting to understand how to ensure aynchronous safety when using an instance of a model when using Node.js.  Here, I use the Mongoose ODM in code samples, but the question applies to any case where a database is used with the asynchronous event-driven I/O approach that Node.js employs.</p>
  
  <p>Consider the following code (which uses Mongoose for MongoDB queries):</p>
  
  <h3>Snippet A</h3>
  
  <pre><code>MyModel.findOne( { _id : &lt;id #1&gt; }, function( err, doc ) {
      MyOtherModel.findOne( { _id : someOtherId }, ( function(err, otherDoc ) {
          if (doc.field1 === otherDoc.otherField) {
              doc.field2 = 0; // assign some new value to a field on the model
          }
          doc.save( function() { console.log( 'success' ); }
      });
  });
  </code></pre>
  
  <p>In a separate part of the application, the document described by MyModel could be updated.  Consider the following code:</p>
  
  <h3>Snippet B</h3>
  
  <pre><code>MyModel.update( { _id : &lt;id #1&gt; }, { $set : { field1 : someValue }, callback );
  </code></pre>
  
  <p>In Snippet A, a MongoDB query is issued with a registered callback to be fired once the document is ready.  An instance of the document described by MyModel is retained in memory (in the "doc" object).  The following sequence could occur:</p>
  
  <ol>
  <li><strong>Snippet A</strong> executes</li>
  <li>A query is initiated for MyModel, registering a callback (callback A) for later use</li>
  <li><em>&lt;&lt; The Node event loop runs >></em></li>
  <li>MyModel is retrieved from the database, executing the registered callback (callback A) </li>
  <li>A query is initiated for MyOtherModel, registering a callback for later use (callback B)</li>
  <li><em>&lt;&lt; The Node event loop runs >></em></li>
  <li><strong>Snippet B</strong> executes</li>
  <li>The document (id #1) is updated</li>
  <li><em>&lt;&lt; The Node event loop runs >></em></li>
  <li>MyOtherModel is retrieved from the database, executing the registered callback (callback B)</li>
  <li>The stale version of the document (id #1) is incorrectly used in a comparison.</li>
  </ol>
  
  <h2>Questions</h2>
  
  <ol>
  <li>Are there any guarantees that this type of race condition won't happen in Node.js/MongoDB?  </li>
  <li>What can I do to deterministically prevent this scenario from happening?  </li>
  </ol>
  
  <p>While Node runs code in a single-threaded manner, it seems to me that any allowance of the event loop to run opens the door for potentially stale data.  Please correct me if this observance is wrong.</p>