We recently released two pieces on accounting principles for developers building products that move money. Part I covered basic accounting principles like debits and credits, account normality, and dual aspect. In Part II, we walked through how to apply these principles to build a Venmo clone.
This follow-up will explore the accounting principles behind a lending app. Here, we’ll look at a consumer lending marketplace akin to Lending Club that we’ll call Modern Lending. While we are showcasing a lending marketplace, you will find that the principles presented here are applicable to most types of lending ledgers.
Who This Guide Is For
This guide is ideal for developers who are building products that feature a lending component and operate at some scale.
For lending applications, keeping track of money using double-entry is especially important. Double-entry ensures funds are not created or destroyed out of nothing, and balances are always accurate. Using double-entry constraints in database development is a best practice for fintechs and other companies that move money (read more about this topic in our article How And Why Homegrown Ledgers Break and the public examples of Uber, Square, and Airbnb).
Why Double Entry
As a reminder, obeying double-entry accounting rules boils down to following these principles:
- Your ledger should be composed of accounts and transactions;
- Accounts represent the balances your ledger will track. They can be classified as debit normal or credit normal.
- Transactions represent business events that have a monetary impact. They are composed of multiple entries (at least two). Each entry can be on the debit side or credit side.
- The aggregate balance of all credit normal accounts and all debit normal accounts in a ledger should net out to zero (credits = debits).
Building Modern Lending
Step 1: Reviewing The Use Case
Let’s start with the requirements for our fictitious Modern Lending. This is a peer-to-peer lending marketplace where individuals can add money to a shared pool of cash managed by Modern Lending. These investors can then set their risk preferences, accept interest rates and invest directly on the platform.
Modern Lending then lends out the money to borrowers on the platform, adjusting the amount and interest rate based on their creditworthiness. Borrowers pay back their principal balance over time, and after repayments, Modern Lending returns capital to investors, plus interest. Modern Lending recognizes (books) the spread between the interest it gets paid by borrowers and the interest it pays to investors as revenue.
This translates into the following set of product requirements:
- Users should be able to self-select as investors or borrowers during onboarding;
- For investors:
- During onboarding, they would choose between a set of investing options, varying by term (when they get their money back) and interest rate (how much they get in return).
- After onboarding, they would wire or ACH their committed investment into the Modern Lending cash pool. This investment would be represented in their account as a balance.
- At the end of their chosen term, they receive their principal back plus interest.
- For borrowers:
- During onboarding, they would submit information about creditworthiness and income.
- They would then receive a list of potential loans they can take varying by amount, term, and interest rate.
- Next, they would pick one of these loans and have money disbursed to them in the form of a wire, ACH, or RTP transfer.
- Over time, the borrower would make repayments in the platform against their principal and interest balance, which would be represented in-app.
Let’s assume there are no transaction costs or fees. We will also assume we are building this application for scale—Modern Lending should be configured to handle thousands of investors and borrowers triggering disbursements and collections every day. Finally, let’s also assume we would like to build our ledger flexibly to accommodate future product expansions.
This scenario creates a set of ledgering requirements:
- Transactions need to be logged as they happen. For this, we will need a ledger API that embeds directly into our application code and writes into the ledger database as business events happen. Modern Lending needs to parse financial transactions and dictate how to write in the ledger—we’ll call this ‘translation’ service transaction handling logic.
- Balances need to be kept up to date consistently and automatically. Transactions need to be parsed appropriately in order to update the correct balances. Aggregations need to be efficient, and balances need to be updated within milliseconds of a transaction taking place. They also need to be queryable to support transactions such as showing the user an updated balance after a transaction is completed. For this to be true, we need to map our accounts to their given normality—a set of constraints that will help the ledger obey double-entry rules. Such constraints are represented in a chart of accounts.
- The ledger needs to accommodate a high volume of financial transactions and be built flexibly to expand our product offerings in the future. In essence, this needs to be a central ledger that is divorced from fund movements (i.e., our underlying bank account setup) and is fully programmatic and flexible. The ledger’s functionality and underlying data models should not be tightly coupled to business logic.
In the next sections, we discuss the accounting setup—first, our chart of accounts, then our transaction handling logic.
Step 2: Reviewing the Data Flow
Before we start with the ledgering setup, it’s important for us to understand how data flows in a lending system. Modern Lending would need to implement the following services infrastructure alongside its ledger.
There are two kinds of data Modern Lending needs to keep track of:
- Historical data, or data that reliably represents the current financial state of Modern Lending based on posted transactions.
- Prospective data, specifically those that are defined by the business model: interest rates, loan terms, payment amounts, and the payment breakdown of interest versus principal.
Modern Lending will need to make use of an amortization schedule, a tool that utilizes interest rates, principal, and loan term to define monthly payments. It is also common for lending businesses to front-load the percentage of a customer’s payments that goes towards interest versus principal. An internal service on Modern Lending’s backend can track this data and modify outputs based on new inputs (i.e., new loan terms).
The ledger database acts in tandem with the amortization schedule. The ledger acts as the source of truth for historical information. Every time the amortization schedule service needs to provide an updated view of current balances, it cross-references the amortization schedule with the ledger database to provide accurate data.
Keeping historical information in the ledger and the amortization schedule outside of the ledger keeps Modern Lending’s data store clean and referenceable over the course of the lifetime of the loan.
Notice that the ledger also needs to interact with another service divorced from the underlying ledger: payments and reconciliation logic. This service is our way of representing Modern Lending’s payment processor of choice: this can be a card processor or Modern Treasury Payments API if you’re using ACH, wire, or RTP. Transactions come in as webhooks and get parsed as ledger transactions according to the rules presented below.
Step 3: Building Your Chart Of Accounts
A chart of accounts is a simple depiction of the accounts Modern Lending will need, their type, and normality.
Let’s review this in detail. First, we have two general accounts: cash and revenue. Cash tracks the overall cash position of Modern Lending. As it represents a use of funds, it is a debit normal account. Revenue, on the other hand, represents a tally of how much money we recognize (book) as revenue during the regular course of business. It is a credit normal account because it represents a source of funds. For the sake of this example, Modern Lending has a single revenue stream: interest.
You may have noticed we have a set of “n of” accounts. This is our way of representing that each investor and each borrower will have two sets of accounts: one tracking principal and one tracking interest. While we will only need one cash and one revenue account, we need multiple sets of user accounts.
Principal accounts track total capital invested by investors and total capital lent to borrowers. The investor principal accounts are credit normal because they represent sources of funds—or funds Modern Lending owes. Conversely, borrower principal accounts are debit normal because they represent uses of funds—akin to receivables.
Finally, interest accounts track the interest balance for both investors and borrowers. They follow the same normality rules as the principal accounts: they are credit normal when they track interest due to investors and debit normal when they track interest that is owed to Modern Lending by the borrowers.
Step 4: Mapping Transaction Logic
Let’s consider the typical set of events that will hit the ledger. As mentioned before, a stream of transactions is parsed through the internal service handling payments and reconciliation. Transactions are then written into the ledger according to the rules presented below. The examples below are meant to be illustrative of what transaction handling logic looks like - there are other transaction types not presented here Modern Lending would need to parse out.
Here we cover the following archetypical transactions:
- Investor deposit. An investor adds money to their balance.
- Borrower disbursement. A borrower initiates a loan and receives funds.
- Interest calculation. Monthly interest gets added to the interest balance for both borrowers and investors. As part of this calculation, part of the interest gets recognized as booked revenue.
- Borrower repayment. A borrower repays monthly installments covering both interest and principal.
- Investor withdrawal. At the end of their term, Modern Lending sends principal plus interest owed to investors.
In this example, we’ll simplify our marketplace down to one investor (Brittany) and one borrower (Art). We’ll also assume the following data about our loans is coming from our amortization schedule:
- Brittany is depositing $10,000 as an investor and expects a 4.8% return upon completion of her 1-year term. This equates to a payment of $10,480 to her at the end of month 12, or $10,000 in principal plus $480 in interest.
- Art is borrowing $5,000 and will pay 12% annual interest over the course of his 1-year loan. This equates to $600 in interest at the end of the year. If we also assume simple interest calculations and monthly payments, the amortization schedule also informs our ledger that Art needs to make monthly payments of $466.67, with $416.67 ($5,000 / 12) of this being directed towards principal, and $50 ($600 / 12) directed towards interest.
Transaction Type 1. Investor deposit
As Brittany deposits money on the Modern Lending platform, we debit (increase) the cash account and credit (increase) Brittany’s investor balance account. Brittany’s interest rate is fetched from our amortization schedule.
Notice that we don’t record any kind of interest due to Brittany on the ledger at this time, regardless of the fact Brittany was promised a 4.8% return upon sign-up. Interest is ledgered in a separate transaction (see below).
Transaction Type 2. Borrower disbursement
When Art is approved for a loan and receives $5,000, we credit (decrease) our cash account and debit (increase) Art’s principal due account. As above, notice we do not record any kind of interest owed by Art at this time.
Transaction Type 3. Interest calculation
Recall that Brittany lent $10,000 and expects a 4.8% return in a year. That means her effective interest payment at maturity (when the loan is due) equates to $480. Given we are assuming simple interest, we can see that we should add $40 to her interest balance to the ledger every month ($480/12). This is a credit because we are increasing a credit normal account.
As outlined before, Art borrowed $5,000 at 12% to be paid in a year. This means Art’s final interest balance will be $600 at the end of the year. Assuming simple interest again, our ledger should add $50 every month to Art’s interest balance ($600/ 12). This is a debit because we are increasing a debit normal account. (Let’s assume Brittany’s remaining $5,000 just sits on Modern Lending’s cash account for now).
At the end of the year, Modern Lending will have received $600 from Art and will owe Brittany $480 in interest. The difference of $120 is recognized as revenue. Every month, as interest gets calculated, we add $10 to our revenue account ($120 / 12).
You may be wondering why we recognize revenue as interest gets calculated, as opposed to when a borrower pays out their repayments or when an investor receives their payout. There is a difference between booked revenue (accrual) and realized revenue (cash). These two concepts are borne from accrual and cash accounting principles.
In this case, we are using accrual accounting and booking revenue at the point in which it is earned: when interest is incurred. In a marketplace of hundreds or thousands, these transactions would be handled by a monthly cron job that calculates interest and modifies balances on the ledger at a predetermined date.
Were we using cash accounting, we would add to the realized ledger only after a borrower makes their repayments and investors get paid back. Because your application ledger doesn’t need to comply with GAAP accounting rules, we suggest you pick the method that leads to the cleanest ledger.
Transaction Type 4. Borrower repayment
Every month Art makes a payment towards his balance. At the end of the term of his loan Art will have to pay a total of $5,600, $5,000 in principal, and $600 in interest. This translates into a monthly payment of $466.67.
After the transaction clears, we debit (increase) our cash account by $466.67. In the same transaction, we credit (decrease) both principal and interest balances for Art. Principal gets deducted by $416.67 ($5,000 / 12) and interest gets deducted by $50 ($600 / 12).
At this point, the ledger shows one payment made by Art, a principal balance of $4,583.33 ($5,000 - $416.67), and an interest balance of zero. This happens because we recognized interest in the “interest calculation” section and then immediately zeroed it out as the payment was made. The sum of credits towards Art’s interest balance represents the total paid in interest. We can contrast this with the data from Modern Lending’s amortization schedule to derive Art’s remaining principal balance.
Transaction Type 5. Investor disbursement
Finally, at the end of the year, Brittany would get disbursed her principal of $10,000 in addition to the 4.8% return—or $480—promised to her. We credit (decrease) our cash account, and simultaneously, we lower her principal and interest down to zero by debiting (decreasing) $10,000 and $480, respectively.
Step 5: Bringing It All Together
Let’s review the elements we would need in place to service this use case:
- Modern Lending needs a central ledger that represents the entire collection of accounts and transactions;
- Working with the ledger, we need two services: one that streams transaction data (typically a payments API like Modern Treasury) and one amortization schedule.
- The ledger will need at least six types of accounts:
- One debit normal cash account
- One credit normal revenue from interest account
- One credit normal investor principal account per investor in the platform
- One credit normal investor interest account per investor in the platform
- One debit normal borrower interest account per borrower in the platform
- One debit normal borrower principal account per borrower in the platform.
- Transaction logic that supports at least the following five types of typical transactions:
- Investor deposit
- Borrower disbursement
- Interest calculation
- Borrower repayment
- Investor disbursement
If any of the concepts above are confusing, or you simply need a refresher on debits and credits, take a look at part I of this series here. Bottom line is that while using double-entry is the best way to ensure integrity of the financial information flowing through Modern Lending’s product, it requires a bit of setup and parsing through the most common transactions. While this seems hard at first, understanding accounting principles goes a long way. The hard part—we believe—is setting up the underlying ledger database with the right constraints and level of flexibility.