Contents

In simple terms, double-entry accounting is the money version of the law of conservation of energy.

Just as energy cannot be created or destroyed and can only change form, money in a double-entry system cannot appear or disappear. Every movement of money must have two sides: a source and a destination.

When building financial products, this means money is never just ā€œcreatedā€ inside the system. It is always transferred from somewhere to somewhere else, and both sides must be recorded.

In this article, we’ll learn how to implement correctness and accuracy into your product using double-entry with Blnk.

Double-entry vs single-entry: what's the difference?

Most developers start with single-entry accounting without realising it. You have a balance, you add to it or subtract from it, and you move on.

The problem is that a single-entry system only records what happened to one side. If John deposits $200, you record "+$200 to John's balance." But where did that $200 come from? The ledger doesn't say.

Single-entry Double-entry
Records One side of the transaction Both sides, source and destination
Auditability Hard to trace where money came from Every transaction is fully traceable
Error detection Silent drift, balances go wrong slowly Errors surface immediately
Reconciliation Manual, painful Systematic, every entry has a counterpart
Blnk support āœ—   Not supported āœ“ enforced by design

Double-entry requires every transaction to have two parts: a source balance it leaves and a destination balance it enters. Blnk enforces this on every single transaction request. If you don't provide both, the transaction won't record.

Source and destination

Every transaction is made of three main parts:

  1. How much was sent (amount) .
  2. Who sent it (source).
  3. Who received it (destination).

Blnk enforces this with the source and destination parameters in our transaction request object. When a transaction is created within Blnk, you can always guarantee that this transaction wasn’t generated from thin air.

This matters a lot, because it gives you more control and confidence when the time comes to audit or investigate a problem.

What happens when the source or destination is outside my system

This is a very common use case.

For example: Ada deposited $200 from her bank account to her in-game wallet. The $200 came from outside Blnk. Her bank isn't a balance in your ledger. How do you represent that?

To model this with double-entry, you frame the fund flow as money came from ā€œoutsideā€ to Ada’s wallet.

This means that the source is ā€œoutside,ā€ and the destination is Ada.

```

--CODE language-json--

source: "@Outside",
destination: "ada-balance"

```

@Outside (or whatever name you choose) is an internal balance that represents external inflows. Now when you look at the transaction record in Blnk, you can immediately tell that this was a deposit. The logic now becomes ā€œevery transaction where ā€˜outside’ is the source must be a deposit.ā€

For outflows, when money leaves your system, you reverse it:

```

--CODE language-json--

"source": "ada-wallet-balance",
"destination": "@World"

```

Imagine this for thousands of balances in your system. With this logic, all you now need to retrieve deposits for a particular balance is to filter all balances where the source is outside and the destination is the specified balance.

```

--CODE language-json--

q: "*",
query_by: "destination",
filter_by: "source:=outside-balance"

```

Catching and preventing errors with double-entry

Double-entry in Blnk is represented with a single record. The debit and credit sides are defined by the source and destination balances respectively.

This means that:

  1. 1:1 money movement: Every transaction maps a single source to a single destination. If the amount is $20, that exact $20 is deducted from the source and added to the destination. You record the amount once, removing the risk of creating money by accident.
  2. No half-recorded transactions: A common cause of missing money is recording one side and forgetting to record the other side. Blnk helps you prevent that out of the box. Your transaction will not be recorded if both sides are not provided.
  3. Deterministic balances: Because every transaction has two sides, balances will always be the result of easily traceable transactions. If a balance looks wrong, you know the issue must come from a specific transaction rather than silent drift over time.
  4. Clear error surfaces: With double entry, balance errors always come down to two things: wrong amount and wrong counterparty. This drastically narrows down the search space when something goes wrong and you need to dig deep into your ledger.

Example:Ā Building a credit card flow on double-entry

Jasmine was tasked with building a new ledger for her team’s new credit card product. As a core requirement, the product would accrue owed cash spent by the user plus interest accrued on the outstanding loan.

To implement it with Blnk’s double entry, she needs to start with 1 question:

How many times will money move?

For Jasmine, money moves three times:

  1. When cash is spent
  2. When interest is accrued
  3. When the credit is repaid

When cash spent is being accrued.

When a user spends money on credit, their balance goes negative. A negative balance means the user owes that amount to the business.

This setup makes debt visible immediately. Any negative balance clearly represents an outstanding customer obligation.

```

--CODE language-bash--

source: "user-balance",
destination: "@Outside"

```

In plain terms, value leaves the user’s balance and moves to the outside world. The ledger records this as debt, not lost money.

When interest is being accrued

Accrued interest represents the cost of borrowing over time. Each interest charge increases how much the user owes, which means their negative balance grows.

```

--CODE language-bash--

source: "user-balance",
destination: "@Interest"

```

Because interest is clearly separated in its own money movement, you can also choose to separate the principal from the interest and see how the debt was built up.

When the credit card is paid off

Paying off the credit card means settling the debt and bringing the user balance back to zero.

To do this, the payment flows into the user’s balance, offsetting the negative amount created by spending and interest.

```

--CODE language-bash--

source: "@LoanSettlement"
destination: "user-balance"

```

Use-case tutorials built on double-entry

Every use case below is a direct implementation of the double-entry model above. Start with the one closest to what you're building:

FAQ

  • What's the difference between source and destination in Blnk?Source is the balance money leaves. Destination is the balance money enters. Both are required on every transaction. If either is missing, Blnk rejects the transaction.
  • Can a balance go negative in Blnk?Yes, with allow_overdraft: true. This is intentional and common for internal balances like @World that represent external inflows, or for credit product balances where a negative balance represents money owed.
  • How do I record a fee on a transaction?Create a separate transaction from the user's balance to your internal fee balance such as @RevenueFees. Fees are not edits to the original transaction. They are their own money movement with their own audit trail.
  • What happens if I send the same transaction twice?Blnk uses the reference field to detect duplicates. If the same reference is sent twice, Blnk processes it once and discards the duplicate. Always use a unique, stable reference per transaction.
  • How does double-entry make reconciliation easier?Because every transaction has two sides, you can always reconstruct the full history of any balance by tracing its transactions. Reconciliation becomes a matching exercise rather than a forensic investigation.

In summary

Double-entry is not just a feature. It is a standard, a correctness guarantee for your money.

It requires you to define your flows explicitly even if it means a bit of extra work upfront. This decision will save you a ton of time, money, and energy when your customers grow, volumes increases, and edge case start to appear.

With Blnk in place, it becomes easier to build higher-level workflows:

Instead of worrying about if your balances are correct, you can ask ā€œwhich transactions got us here?ā€ Double-entry turns money into a system that you can always trust, audit, and verify.

Get started with Blnk Core to try out double-entry for your product.

ā€