title: How to cleanly implement concurrency proof transactions within the model using callbacks?
body: <p>Lets say a <code>Transfer</code> moves money from an account to another. This should only be possible if the source account has enough balance.</p>
  
  <p>Given that we are dealing with money, we have to be careful about concurrency. I'm using Postgresql.</p>
  
  <p>The solution should ideally:</p>
  
  <ol>
  <li>Cleanly rollback and add a validation error in case of insufficient balance.</li>
  <li>Be concurrency proof.</li>
  </ol>
  
  <p>After some thought, I think the proper place to implement this business logic would be inside the <code>Transfer</code> model. Here's my first try:</p>
  
  <pre><code>def Transfer &lt; ActiveRecord::Base
    validate :check_account_balance
  
    def check_account_balance
      if from_account.balance &lt; amount
        errors.add(:from_account, "Insufficient balance")
      end
    end
  
    before_create :update_balances
    def update_balances
      from_account.increment!(:balance, -1*amount)
      to_account.increment!(:balance, amount)
    end
  end
  </code></pre>
  
  <p>We make use of the fact that ActiveRecord runs validations and callbacks within a single transaction.</p>
  
  <p>I'm worried for the following concurrent scenario: Two parallel requests pass the <code>check_account_balance</code> and proceed to update the balances. If the account's balance is 1 and the amounts of both transfers are 1, then will this allow for both to go through? How do we fix this? Does this require locking on the account?</p>
  
  <p>Also, how clean is the design of the code and would you do it in a different way?</p>