title: How to model bank transfer in CQRS
body: <p>I'm reading <a href="http://martinfowler.com/apsupp/accounting.pdf">Accounting Pattern</a> and quite curious about implementing it in CQRS.</p>
  
  <p>I think AccountingTransaction is an aggregate root as it protects the invariant:</p>
  
  <p><strong>No money leaks, it should be transfer from one account to another.</strong></p>
  
  <pre><code>public class AccountingTransaction {
      private String sequence;
      private AccountId from;
      private AccountId to;
      private MonetaryAmount quantity;
      private DateTime whenCharged;
  
      public AccountingTransaction(...) {
          raise(new AccountingEntryBookedEvent(sequence, from, quantity.negate(),...);
          raise(new AccountingEntryBookedEvent(sequence, to, quantity,...);
      }
  }
  </code></pre>
  
  <p>When the AccountingTransaction is added to its repository. It publishes several AccountingEntryBookedEvent which are used to update the balance of corresponding accounts on the query side. </p>
  
  <p>One aggregate root updated per db transaction, eventual consistency, so far so good.</p>
  
  <p>But what if some accounts apply transfer constraints, such as cannot transfer quantity more that current balance? I can use the query side to get the account's balance, but I'm worried that data from  query side is stale.</p>
  
  <pre><code>public class TransferApplication {
      public void transfer(...) {
          AccountReadModel from = accountQuery.findBy(fromId);
          AccountReadModel to = accountQuery.findBy(toId);
          if (from.balance() &gt; quantity) {
              //create txn
          }
      }
  }
  </code></pre>
  
  <p>Should I model the account in the command side? I have to update at least three aggregate roots per db transaction(from/to account and account txn).</p>
  
  <pre><code>public class TransferApplication {
      public void transfer(...) {
          Account from = accountRepository.findBy(fromId);
          Account to = accountRepository.findBy(toId);
          Transaction txn = new Transaction(from, to, quantity);
          //unit or work locks and updates all three aggregates
      }
  }
  
  public class AccountingTransaction {
      public AccountingTransaction(...) {
          if (from.permit(quantity) {
              from.debit(quantity);
              to.credit(quantity);
              raise(new TransactionCreatedEvent(sequence, from, to, quantity,...);
          }   
      }
  }
  </code></pre>