 <p>You really should not be calling asynchronous functions inside a synchronous loop. What you need is something that repects the callback on completion of the loop cycle and will alert when the update is complete. This makes incrementing counters externally safe.</p> <p>Use something like <a href="https://github.com/caolan/async#whilsttest-fn-callback" rel="nofollow">async.whilst</a> for this:</p> <pre><code>var i = 0; async.whilst( function() { return i &lt; req.body.app_events.length; }, function(callback) { console.log(req.body.app_events[i].event_key); //delete upsertData._id; Appusers.findOneAndUpdate( { app_key: req.body.app_key, e_key:req.body.app_events[i].event_key}, { $set : { app_key:req.body.app_key, e_key: req.body.app_events[i].event_key, e_name: req.body.app_events[i].event_name } }, { upsert: true}, function(err,data) { if (err) callback(err); console.log(data); i++; callback(); } ); }, function(err) { if (err) console.log(err); else // done; } ); </code></pre> <p>Now the loop is wrapped with a "callback" which is called in itself within the callback to the update method. Also if you expect a "document" back then you should be using <code>.findOneAndUpdate()</code> as <code>.update()</code> just modifies the content and returns the number affected.</p> <p>When the loop is complete or when an error is passed to the callback, then handling is moved to the last function block, where you complete your call or call other callbacks as required.</p> <hr> <p>Better than above. Dig into the native driver methods for <a href="http://docs.mongodb.org/manual/reference/method/Bulk/" rel="nofollow">Bulk</a> operations. You need to be careful that you have an open connection to the database already established. If unsure about this, then try to always wrap application logic in:</p> <pre><code>mongoose.connection('once',function(err) { // app logic here }); </code></pre> <p>Which makes sure the connections have been made. The mongoose methods themselves "hide" this away, but the native driver methods have no knowledge.</p> <p>But this is the fastest possible listing to update the data:</p> <pre><code>var i = 0; var bulk = Appusers.collection.initializeOrderedBulkOp(); async.whilst( function() { return i &lt; req.body.app_events.length; }, function(callback) { console.log(req.body.app_events[i].event_key); bulk.find( { app_key: req.body.app_key, e_key:req.body.app_events[i].event_key}, ).upsert().updateOne({ $set : { app_key:req.body.app_key, e_key: req.body.app_events[i].event_key, e_name: req.body.app_events[i].event_name } }); i++; if ( i % 1000 == 0) { bulk.execute(function(err,response) { if (err) callback(err); console.log(response); bulk = Appusers.collection.initializeOrderedBulkOp(); callback(); }) } else { callback(); } }, function(err) { if (err) console.log(err); else { if ( i % 1000 != 0 ) bulk.execute(function(err,response) { if (err) console.log(err) console.log(response); // done }); else // done } } ); </code></pre> <p>The Bulk methods build up "batches" of results ( in this case 1000 at a time ) and send all to the server in one request with one response ( per batch ). This is a lot more efficient than contacting the database once per every write.</p>