Handling Concurrency

Overview

Every time you check a ledger account balance in your app, you get a snapshot of that balance at a moment in time. As money moves, you need to be confident that that snapshot is accurate even as balances are constantly shifting in real time.

To prevent a double-spend situation, your ledger needs to be able to record transactions that are conditional on the state of an account balance or account version. The Ledgers API provides both of these mechanisms.

Locking on account balance

When creating or updating a ledger transaction, you can send balance filters as part of a ledger entry to validate the balance of the corresponding ledger account if the current ledger transaction were created or updated. If this ledger transaction would cause a ledger account balance to go outside of the specified range, the request will fail with a 422.

The available types of balance filters are pending_balance_amount, posted_balance_amount, and available_balance_amount and the balance may be filtered with gt (>), gte (>=), eq (=), lte (<=), and lt (<).

For example, suppose you are recording a payment moving $1 out of a credit-normal user account. You can specify that the account's available_balance must remain greater than or equal to $0 upon completion of the transaction:

curl --request POST \
     --url https://app.moderntreasury.com/api/ledger_transactions \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
       "effective_at": "2022-01-01T00:00:00.000",
       "status": "pending",
       "ledger_entries": [{
         "amount": 100,
         "direction": "debit",
             "available_balance_amount": { "gte": 0 },
         "ledger_account_id": "89c8bd30-e06a-4a79-b396-e6c7e13e7a12"
       }, {
         "amount": 100,
         "direction": "credit",
         "ledger_account_id": "a30e5616-9408-4e5e-957a-bb0bcea5f0ce"
       }]
     }'

Using the lock_version field

You can specify a lock_version when writing an entry to the ledger account. If the lock_version specified is not the same as the current lock_version of the ledger account balance, the transaction will fail to be created.

For example, suppose you are recording a payment paying out $10.32 from a credit-normal user account. You can specify that the transaction be written if and only if the ledger account has not been updated since you last checked its lock_version:

curl --request POST \
     --url https://app.moderntreasury.com/api/ledger_transactions \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
    "description": "Payout",
    "effective_at": "2022-01-01T00:00:00.000",
    "status": "pending",
    "external_id": "97dbb8b1-e6f2-485e-a0ec-6267e3c60718",
    "ledger_entries": [
       {
          "amount": 1032,
          "direction": "debit",
          "lock_version": 5
            }
         ]
     }'

If the lock_version of your ledger account balance is not 5, meaning there has been another entry written to the account since lock_version 5, the transaction will fail.