DEV Community

Daniel Parkson Tano
Daniel Parkson Tano

Posted on

Tracking Payment Liquidity with FIFO Funding Lots

Moving beyond aggregate balances to understand the real cost of every payout.

A payout account may show enough money to complete a transfer, but that balance alone cannot explain what the transfer costs.

Liquidity is often acquired in separate batches. Each batch may have a different exchange rate, funding date, provider cost, or settlement source. When a payout consumes that liquidity, finance teams need to know which funds were used and what margin remained.

An aggregate balance answers “how much is available?” A funding-lot ledger answers “where did it come from, what did it cost, and which transactions consumed it?”

Represent liquidity as inventory

A funding lot can contain:

reference
funding date
original amount
remaining amount
acquisition rate
status
source metadata
Enter fullscreen mode Exit fullscreen mode

The remaining amount changes as payouts consume the lot, while the original amount and acquisition rate remain part of the audit history.

Allocate oldest liquidity first

FIFO allocation is easy to describe and subtle to implement. One payout may consume the remainder of one lot and continue into the next.

with database_transaction():
    lots = lock_open_lots().order_by("funded_at", "created_at")
    remaining = payout_amount

    for lot in lots:
        if remaining <= 0:
            break

        used = min(remaining, lot.remaining_amount)
        create_allocation(lot=lot, reference=reference, amount=used)
        lot.remaining_amount -= used
        lot.save()
        remaining -= used
Enter fullscreen mode Exit fullscreen mode

Row locks prevent two payouts from consuming the same remaining liquidity concurrently.

Make allocation retry-safe

Before allocating, calculate how much has already been assigned to the transaction reference. A retried task should allocate only the difference.

The database should also prevent the same transaction-lot relationship from being inserted twice accidentally.

Distribute financial values across lots

If one payout spans multiple lots, its revenue and provider fee must be distributed proportionally. Assigning the full revenue or fee to each allocation overstates the transaction.

For each allocation, calculate:

  • share of the total payout;
  • attributed customer revenue;
  • provider-fee share;
  • cost at the lot’s acquisition rate;
  • payout cost excluding provider fee; and
  • resulting FX margin.

The final allocation should absorb rounding differences so the parts equal the original transaction totals exactly.

Reconcile derived values

Financial rules evolve. A reconciliation service should be able to rebuild remaining lot balances and derived allocation values from authoritative transactions without deleting valid live history.

Manual overrides must be explicit and traceable. A corrected revenue value should be marked as an override rather than becoming indistinguishable from a calculated value.

The design principle

Liquidity is financial inventory. Funding lots and immutable allocations make its movement explainable.

This structure supports treasury visibility, transaction-level cost attribution, controlled reconciliation, and reliable margin analysis without relying on today’s aggregate balance to reconstruct yesterday’s economics.

Top comments (0)