Scaling for writes
Writes contention
The Formance Ledger uses a multi-ledger, single-writer, sequential writes architecture to create an auditable, easy to reason about trail of transactions. The latest stable of the ledger is optimised for 1K writes per second on an underlying commodity storage instance. As a result, write heavy applications above this threshold are advised to leverage the Formance Ledger’s segmentation capabilities to scale horizontally. This will allow you to create multiple ledgers and to write to them in parallel.Transaction commit cost breakdown
As outlined in the performance model, we consider the cost of a write to beO(N) + W
. Let’s consider the following example:
@payments:1234
by $99.00, sourcing the funds from three user accounts before defaulting @world
as the source of last resort. Let’s break down the operations that will be performed:
- Read the balance of
@users:1234:main
- If the balance of
@users:1234:main
was less than $99.00, read the balance of@users:1234:vouchers
- If the balance of the previous account was less than $99.00, read the balance of
@users:1234:creditcard
- Model the transaction
- Write the new balance of
@users:1234:main
O(1) + W
and at most O(3) + W
. This is because the transaction will need to read the balance of at least one account, and at most three accounts, and then commit the computed transaction to the ledger.
When optimizing for write throughput, it is important to keep in mind this cost breakdown and to design your transactions accordingly.
Scaling for reads
Chart of accounts
While usually not a concern for the scaling of writes, designing a proper chart of accounts is key to the performance of your reads. You’ll especially want to make sure that the addresses of your accounts are using properly separated segments, as this will allow you to use wildcards to query your accounts. An example of an inefficient account address would beusers:1234_main
Implemented instead as users:1234:main
, the latter will enable the ledger to efficiently query all accounts of a given user by using the users:1234:*
wildcard or all accounts of all users of a given type by using the users:*:main
wildcard.