Skip to main content
This guide covers best practices for designing your chart of accounts in Formance Ledger, with a focus on handling real-world financial scenarios like debts, credit lines, and liabilities.

Allowing Negative Balances

In Formance, accounts can be configured to carry negative balances, enabling accurate modeling of real-world financial obligations such as debts, credit lines, pending payments, or unsettled invoices.

Why allow negative balances?

Allowing an account to go negative is a common way to represent liabilities or temporary obligations. For example:
  • A user owes funds to a platform or another user
  • A credit line that can be drawn upon
  • Pending settlements awaiting clearing
  • Unsettled invoices
The account balance reflects that deficit until the obligation is cleared.

Enabling overdraft

To allow an account to have a negative balance, use the allowing overdraft clause in Numscript:
send [USD/2 1000] (
  source = @users:alice allowing unbounded overdraft
  destination = @users:bob
)
Or with a bounded overdraft:
send [USD/2 1000] (
  source = @users:alice allowing overdraft up to [USD/2 500]
  destination = @users:bob
)
See Overdraft for more details on overdraft syntax.

Debt Settlement Example

When a user pays off a debt, the transaction simply reduces the negative balance on the debtor’s account. This brings the balance closer to zero (or above), effectively recording the settlement of the liability.

Scenario

  1. Alice owes 100toBob(Alicesbalance:100 to Bob (Alice's balance: -100)
  2. Alice pays $50 to Bob
  3. Alice’s balance becomes -$50
// Initial debt creation (Bob lends to Alice)
send [USD/2 10000] (
  source = @users:alice allowing unbounded overdraft
  destination = @users:bob
)

// Debt repayment (Alice pays back Bob)
send [USD/2 5000] (
  source = @users:alice
  destination = @users:bob
)
This mirrors standard double-entry accounting, where one account’s reduction offsets another’s increase.

Best Practices for Account Naming

Avoid world as a generic source

To ensure clarity and traceability in your ledger:
Avoid introducing funds from the generic world account for business transactions.
Use specific account addresses like users:123:payment:4567 to represent the exact source or context of the transaction.

Why this matters

  • Audit trail: Specific addresses maintain a transparent record of where funds originated
  • Context: Stakeholders can understand the purpose of each transaction
  • Debugging: Easier to trace issues when accounts have meaningful names

Good vs. bad examples

BadGood
@world@users:alice@users:alice:payment:order-123@platform:revenue
Generic sourceSpecific, contextual source

When to use world

The world account is appropriate for:
  • Initial system bootstrapping
  • Minting new assets (e.g., loyalty points, tokens)
  • Non-funded currency conversions (see Currency Conversion)

Structuring Account Hierarchies

Use colons (:) to create meaningful account hierarchies:
users:{user_id}:wallet:main
users:{user_id}:wallet:pending
users:{user_id}:payment:{payment_id}

merchants:{merchant_id}:earnings
merchants:{merchant_id}:settlements

platform:fees
platform:revenue
platform:taxes:{tax_type}

orders:{order_id}:authorization
orders:{order_id}:capture
orders:{order_id}:refund

Benefits of hierarchical naming

  1. Filtering: Query all accounts matching a pattern (e.g., users:123:)
  2. Organization: Logical grouping of related accounts
  3. Scalability: Easy to add new account types without restructuring

Modeling Common Financial Scenarios

E-commerce Platform

# Customer accounts
customers:{id}:wallet

# Merchant accounts
merchants:{id}:earnings
merchants:{id}:settlements

# Order-specific accounts
orders:{id}:pending
orders:{id}:captured

# Platform accounts
platform:fees
platform:taxes:vat
platform:refunds:pool

Lending Platform

# Borrower accounts (can go negative)
borrowers:{id}:principal
borrowers:{id}:interest

# Lender accounts
lenders:{id}:available
lenders:{id}:deployed

# Loan-specific accounts
loans:{id}:outstanding
loans:{id}:payments

Multi-currency Wallet

# User wallets per currency
users:{id}:wallet:USD
users:{id}:wallet:EUR
users:{id}:wallet:BTC

# Exchange accounts
exchange:liquidity:USD
exchange:liquidity:EUR
exchange:fees

Summary

ConceptRecommendation
Negative balancesUse allowing overdraft for liabilities and debts
Account namingUse specific, contextual addresses instead of world
HierarchyUse colons to create logical groupings
Debt settlementReduce negative balances through standard transactions
For more information on the source-destination model and how it differs from traditional double-entry accounting, see Source-Destination Accounting Model.