What is a payment rail?

Payment rail

A payment rail is the network that moves money between banks or wallets. ACH, RTP, FedNow, and wire are rails. A ledger is not a rail. The rail settles the bank money. The ledger records who owes whom while that happens.

How does a payment rail work?

A sender’s bank puts an instruction on the network. The network clears it with the receiver’s bank. Hours or days later, the banks settle. Your product sits in the middle: it takes the customer’s request, talks to a bank or PSP, and waits for the rail to finish.

Payment rail vs ledger

The rail moves central-bank or commercial-bank money. The ledger is your book of record. If you treat the rail as the source of truth, every retry and every partial file becomes a dispute. If you treat the ledger as the book, the rail is an event you record and reconcile.

Which rail should you use?

Pick the rail for speed, cost, and whether the payment can be reversed. ACH is cheap and slow. Same-day ACH is still ACH. RTP and FedNow are instant and usually final. Wires are high-value and expensive. Cards are a different network with their own chargebacks.

RailSpeedTypical use
ACHHours to daysPayroll, bill pay, bank transfers
RTPSecondsAccount-to-account, request for pay
FedNowSecondsInstant US bank payments
WireMinutes to hoursLarge, one-off transfers

How it works with Blnk

Blnk records the movement. Your bank or PSP still sends it on ACH, RTP, FedNow, or wire.

You post from a named source to a named destination when the customer sends or receives. For a deposit, the source is @WorldUSD_ACH and the destination is the customer wallet. Keep the amount inflight until the rail settles, then commit. If the rail fails or returns, void it.

We use @WorldUSD_ACH because it is a system balance that belongs to the organization. Blnk calls these internal balances.

Record a deposit in four steps:

  1. Name the source and destination

    The source is the balance that loses the amount. The destination is the balance that gains it. For this deposit, debit @WorldUSD_ACH and credit the customer wallet.

  2. Record the transfer inflight

    Create the transaction with inflight: true. Settled balances stay unchanged until you commit or void.

    record-deposit.ts
    await blnk.Transactions.create({
      precise_amount: 25000,
      precision: 100,
      reference: 'pay_in_20260816_001',
      currency: 'USD',
      source: '@WorldUSD_ACH',
      destination: 'customer_wallet_id',
      description: 'Deposit via ACH',
      inflight: true,
      meta_data: {
        rail: 'ach',
        processor: 'modern_treasury',
        external_id: 'pt_9c2e1a74',
        customer_id: 'cus_8f21a4',
      },
    });
  3. Commit the settlement or void a failure

    Commit when the rail settles. Void the post if the rail fails or returns. See update inflight.

    Commit
    await blnk.Transactions.updateStatus(
      'txn_c4e70eb8-e4d6-4e04-a2e2-92a43b969e0c',
      { status: 'commit' },
    );
    Void
    await blnk.Transactions.updateStatus(
      'txn_c4e70eb8-e4d6-4e04-a2e2-92a43b969e0c',
      { status: 'void' },
    );
  4. Match the bank or PSP file

    Upload the bank or PSP file in reconciliation and match each line so one ledger covers every rail.