How to collect and disburse millions worth of payments securely.

Illustration showing payment collections and disbursements.

What is Disbursement?

A company needs to create disbursement checks for a multitude of payment types including:

  • Payroll expenses
  • Payments to suppliers, contractors, and vendors
  • Reimbursements to workers for out-of-pocket expenses
  • Dividend payments to shareholders
  • Profit distributions to other business owners

Responsibilities and features

There was a need to build a single authority system that takes care of the following responsibilities:

  1. Avoid over-payments: Disbursing the funds more than the funds collected from the company (including the in-flight amount) is a loss.
  2. Able to consume payment status: It’s not a rare occasion to have payment failure, this module should be able to rollback the calculation if there’s a failure.
  3. Check on the credit-limit: It’s common practice for businesses to allow credit-limit to their clients. At any point in time, the system should able to keep current credit per client.

Data models and Flow

Based on the above requirements, it seems a classic problem of transactions and its accounting. But with the variations, this module will be used as an intermediate account rather instead of a terminal bank-account. Let’s call it BalanceAccount, which will have three book-keeping variables for

  1. Collections: will be stored in amountCollected
  2. Disbursements: will be stored in amountDisbursed

Important metrics to be observed

The above 3 variables are sufficient to determine important states of the accounting system.

Overpayment = amountDisbursed - trueAmount
FrontedAmount = amountDisbursed — amountCollected
DeficitAmount = trueAmount - amountCollected

Data Models

  • BalanceAccount
    - trueAmount: Current amount should be for the beneficiary (either for profit/payroll).
    - amountCollected: Amount received from the company.
    - amountDisbursed: Amount paid ahead to the beneficiary.
    - companyId: Primary Id for the company.
    - amountTxn: List of all instances of amount records attributed.
    - collectedTxn: List of transactions collected and are attributed.
    - disbursedTxn: List of transactions disbursement and attributed.
  • Transactions
    - amount: Amount this transaction is carrying.
    source: The entity where the amount will be debited.
    - destination: The entity where the amount will be credited.
    - transactionDate: This date will help to attribute quarter and year.

Data Flow

Each Transaction will commit the amount in the BalanceAccount as per the source and destination. This commit has to be atomic and in isolation from the concurrent calls. In case of failure, there will be a reverse commit to rollback the amount.

Data-flow diagram representing connection with relevant entities.

Implementation with MongoDB

MongoDB 3.6 has vast adaptation across industries but does not support any notion of a transaction across a document or multiple documents. It does however guarantee atomic operations on single documents. Migrating DB to MongoDB 4+ could be a huge investment depending upon the vastness of the code-base.


For commit, we need to push the transaction to the list and increase the amount atomically.

def commit(transaction):     


If transactions under the window of rollback, we need to do the atomic reverse of the commit operation.

def rollback(transaction): 
assert transaction.canRollback

Sample Code Snippet using Django ORM

Further reading

To learn more about accounting and transactions, MongoDB has recommended an approach here



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Arink Verma

Arink Verma


Code, arts, process and aspirations. co-Founded GreedyGame | IIT Ropar. Found at