Multi-Debit, Multi-Credit Transfers
TigerBeetle is designed for maximum performance. In order to keep it lean, the database only supports simple transfers with a single debit and a single credit.
However, you'll probably run into cases where you want transactions with multiple debits and/or credits. For example, you might have a transfer where you want to extract fees and/or taxes.
Read on to see how to implement one-to-many and many-to-many transfers!
Note that all of these examples use the Linked Transfers flag (
flags.linked
) to ensure that all of the transfers succeed or fail together.
One-to-Many Transfers
Transactions that involve multiple debits and a single credit OR a single debit and multiple credits are relatively straightforward.
You can use multiple linked transfers as depicted below.
Single Debit, Multiple Credits
This example debits a single account and credits multiple accounts. It uses the following accounts:
- A source account
A
, on theUSD
ledger. - Three destination accounts
X
,Y
, andZ
, on theUSD
ledger.
Ledger | Debit Account | Credit Account | Amount | flags.linked |
---|---|---|---|---|
USD | A | X | 10000 | true |
USD | A | Y | 50 | true |
USD | A | Z | 10 | false |
Multiple Debits, Single Credit
This example debits multiple accounts and credits a single account. It uses the following accounts:
- Three source accounts
A
,B
, andC
on theUSD
ledger. - A destination account
X
on theUSD
ledger.
Ledger | Debit Account | Credit Account | Amount | flags.linked |
---|---|---|---|---|
USD | A | X | 10000 | true |
USD | B | X | 50 | true |
USD | C | X | 10 | false |
Multiple Debits, Single Credit, Balancing debits
This example debits multiple accounts and credits a single account.
The total amount to transfer to the credit account is known (in this case, 100
), but the balances
of the individual debit accounts are not known. That is, each debit account should contribute as
much as possible (in order of precedence) up to the target, cumulative transfer amount.
It uses the following accounts:
- Three source accounts
A
,B
, andC
, withflags.debits_must_not_exceed_credits
. - A destination account
X
. - A control account
LIMIT
, withflags.debits_must_not_exceed_credits
. - A control account
SETUP
, for setting up theLIMIT
account.
Id | Ledger | Debit Account | Credit Account | Amount | Flags |
---|---|---|---|---|---|
1 | USD | SETUP | LIMIT | 100 | linked |
2 | USD | A | SETUP | 100 | linked , balancing_debit , balancing_credit |
3 | USD | B | SETUP | 100 | linked , balancing_debit , balancing_credit |
4 | USD | C | SETUP | 100 | linked , balancing_debit , balancing_credit |
5 | USD | SETUP | X | 100 | linked |
6 | USD | LIMIT | SETUP | -0 | balancing_credit |
If the cumulative credit balance of A + B + C
is less than
100
, the chain will fail (transfer 6
will return exceeds_credits
).
Many-to-Many Transfers
Transactions with multiple debits and multiple credits are a bit more involved (but you got this!).
This is where the accounting concept of a Control Account comes in handy. We can use this as an intermediary account, as illustrated below.
In this example, we'll use the following accounts:
- Two source accounts
A
andB
on theUSD
ledger. - Three destination accounts
X
,Y
, andZ
, on theUSD
ledger. - A compound entry control account
Control
on theUSD
ledger.
Ledger | Debit Account | Credit Account | Amount | flags.linked |
---|---|---|---|---|
USD | A | Control | 10000 | true |
USD | B | Control | 50 | true |
USD | Control | X | 9000 | true |
USD | Control | Y | 1000 | true |
USD | Control | Z | 50 | false |
Here, we use two transfers to debit accounts A
and B
and credit the Control
account, and
another three transfers to credit accounts X
, Y
, and Z
.
If you looked closely at this example, you may have noticed that we could have debited B
and
credited Z
directly because the amounts happened to line up. That is true!
For a little more extreme performance, you might consider implementing logic to circumvent the control account where possible, to reduce the number of transfers to implement a compound journal entry.
However, if you're just getting started, you can avoid premature optimizations (we've all been there!). You may find it easier to program these compound journal entries always using a control account -- and you can then come back to squeeze this performance out later!