title: Do asynchronous plausibility checks cause race conditions to arise?
body: <p>I have a .Net 5 Web API project using EF Core and thought about data consistency for my business handlers. I personally think this question is not technology related and applies to other web frameworks as well. The following is just an example (the design might be bad)</p>
  <p>Imagine the API provides two endpoints</p>
  <ul>
  <li><code>POST /users/{userId}/documents/{documentId}</code> to link a user to a document</li>
  <li><code>DELETE /users/{userId}</code> to delete a user</li>
  </ul>
  <p>The database holds a cross table</p>
  <div class="s-table-container">
  <table class="s-table">
  <thead>
  <tr>
  <th>User</th>
  <th>Document</th>
  </tr>
  </thead>
  <tbody>
  <tr>
  <td>User1</td>
  <td>Document1</td>
  </tr>
  <tr>
  <td>User1</td>
  <td>Document2</td>
  </tr>
  <tr>
  <td>User2</td>
  <td>Document2</td>
  </tr>
  </tbody>
  </table>
  </div>
  <p>The logic to link a user to a document might look like</p>
  <pre><code>var user = await FetchUserFromDb(userId);
  
  if(user == null) 
  {
      return new NotFoundResponse($&quot;user {userId} not found&quot;);
  }
  
  var document = await FetchDocumentFromDb(documentId);
  
  if(document == null) 
  {
      return new NotFoundResponse($&quot;document {documentId} not found&quot;);
  }
  
  var insertResult = await InsertIntoCrossTable(userId, documentId);
  
  return new CreatedResponse(insertResult);
  </code></pre>
  <p>The logic to delete a user might look like</p>
  <pre><code>var affectedRows = await DeleteUserFromDb(userId);
  
  if(affectedRows == 0) 
  {
      return new NotFoundResponse($&quot;user {userId} not found&quot;);
  }
  
  return new NoContentResponse(&quot;user deleted successfully&quot;);
  </code></pre>
  <p>Currently, I don't know what happens if both requests come in at the same time. The POST request would successfully return the user and then try to retrieve the document from the database. If the user is deleted at this point, the business logic in the POST request will no longer be aware of this. The insert query statement would throw a database exception because the foreign key for the user no longer exists.</p>
  <p>Am I wrong here and the requests are processed one after the other? Or do I as a developer have to deal with this issue specifically (by adding additional try/catch statements for database exceptions)?</p>