title: How can I use mongodb to only allow one entry when multiple servers are accessing the database?
body: <p>I have multiple &quot;worker&quot; servers processing jobs and accessing the same MongoDB database but I only want one message to be created and never allow two servers running the same job to create the same message.</p>
  <p>When a message is sent, its <code>status</code> field is set to &quot;sent&quot; or if it's disabled it's set to &quot;disabled&quot;.  So first it checks if there are any sent or disabled messages.  Then it creates a document with a <code>lockedAt</code> field set to the current time and checks if the same message has already been locked.  The reason I use the <code>lockedAt</code> field is so that if the job fails for some reason, it will allow the lock to expire and run again.</p>
  <p>This seems to work most of the time but there are a few messages getting through if two &quot;workers&quot; run the same job within a few milliseconds so my logic isn't perfect but I can't figure out how duplicate messages are being created.</p>
  <p>How can I use MongoDB to prevent the same job from running at the exact same time and creating the same message twice?</p>
  <pre><code>// Check if there is a locked message.
  // insert a new message or update if one is found but return old message (or nothing if one didn't' exist)
  const messageQuery = {
      listingID: listing._id,
      messageRuleID: messageRule._id,
      reservationID: reservation._id
  };
  
  let message = await Message.findOne({
      ...messageQuery,
      ...{status: {$in: [&quot;disabled&quot;, &quot;sent&quot;]}}
  });
  // If message has been sent or is disabled don't continue
  if (message) {
      return;
  }
  
  message = await Message.findOneAndUpdate(
      messageQuery,
      {
          listingID: listing._id,
          messageRuleID: messageRule._id,
          reservationID: reservation._id,
          lockedAt: moment().toDate() // Check out the message with the current date
      },
      {upsert: true}
  );
  // If no message is defined, then it's new and not locked, move on.
  if (message) {
      // If message has been locked for less than X minutes don't continue
      const cutoff = moment().subtract(
          Config.messageSendLock.amount,
          Config.messageSendLock.unit
      );
      if (message.lockedAt &amp;&amp; moment(message.lockedAt).isAfter(cutoff)) {
          // Put the last lock time back
          await Message.findOneAndUpdate(messageQuery, {lockedAt: message.lockedAt});
          return;
      }
  }
  </code></pre>