Skip to content

Intra-bank transfer engine

ID MOD-141
System SD04
Repo bank-payments
Build status Deployed
Deployed Yes
Last commit 178e49975435ec5926a3b4f612f5d9ee9efc8495

Purpose

Detects when both the payer and payee hold accounts at the same institution and executes the transfer as a direct book transfer — a single atomic double-entry posting — rather than routing through an external payment rail. Intra-bank transfers are immediate, carry no settlement risk, incur no external rail fees, and are not subject to cut-off windows.

When intra-bank transfer applies

Before routing a payment to an external rail (NPP, Payments NZ RTC, or batch), the payments system resolves the destination account identifier. If the destination account number or identifier resolves to an account held within the same institution, the payment is routed to the intra-bank transfer engine rather than any external rail.

The routing decision is made transparently to the customer: the confirmation screen labels the transfer as an immediate transfer and shows both the debit from the source account and the credit to the destination account. Customers do not see references to NPP or Payments NZ for intra-bank payments because no external rail is involved.

Intra-bank routing applies to:

  • Transfers between a customer's own accounts at the same institution (savings to transaction, transaction to term deposit on maturity).
  • Transfers from one customer's account to another customer's account at the same institution (personal payment, SME director paying company account).
  • Internal platform operations: fee collection from a customer account to an institution fee income account, interest postings from institution funding accounts.
  • Batch payment items (via MOD-135): when a batch contains items where the destination resolves to an internal account, those items are routed to the intra-bank engine rather than the external batch rail.

Advantages over external rail

Property Intra-bank book transfer External payment rail
Settlement timing Immediate — same transaction Minutes (NPP) to next business day (batch)
Settlement risk None — single atomic posting Counterparty and settlement risk between dispatch and settlement
External fees None Per-transaction or volume fees payable to rail operator
Cut-off windows None — 24/7/365 Batch rails have cut-off times; some real-time rails have maintenance windows
Failure modes Database transaction failure — fully atomic External rejection, timeout, settlement failure

AML considerations

Intra-bank transfers are not exempt from AML transaction monitoring. Internal transfers between accounts at the same institution are a well-documented money laundering typology: a customer receives funds from an external source and immediately moves them between their own accounts to obscure origin before withdrawal or onward transfer (layering).

For this reason, every intra-bank transfer passes through the same transaction fraud scoring (MOD-023) and AML screening pipeline as an external payment. The intra-bank routing flag is visible in the transaction record for analytical purposes, but it does not alter the screening logic or thresholds applied.

Data model

-- payments.intra_bank_transfers
CREATE TABLE payments.intra_bank_transfers (
  transfer_id             UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  source_account_id       UUID NOT NULL,
  destination_account_id  UUID NOT NULL,
  amount                  NUMERIC(18,2) NOT NULL CHECK (amount > 0),
  currency                TEXT NOT NULL,
  reference               TEXT,
  initiated_by            UUID NOT NULL,  -- customer or staff member ID
  channel                 TEXT NOT NULL CHECK (channel IN ('app','api','back_office','batch')),
  posting_id              UUID,           -- set when MOD-001 posting succeeds
  fraud_score_result      TEXT,           -- result code from MOD-023
  status                  TEXT NOT NULL DEFAULT 'pending'
                          CHECK (status IN ('pending','posted','failed')),
  failure_reason          TEXT,
  created_at              TIMESTAMPTZ NOT NULL DEFAULT now()
);

The posting_id references the double-entry posting created in MOD-001. The atomicity guarantee is at the database transaction level: the payments.intra_bank_transfers row is updated to posted in the same database transaction that creates the MOD-001 posting. If either write fails, both are rolled back.

Key operations

Initiation and routing detection. The payments orchestrator resolves the destination account identifier. If the account exists in the platform's account registry, the payment is flagged as intra-bank and routed here. If resolution fails (account not found internally), the payment is routed to the appropriate external rail based on the destination identifier format.

Pre-payment validation. MOD-020 runs pre-payment validation on the source account: available balance check (via MOD-003), account status check (not frozen, not closed), and transaction limit check. If any check fails, the transfer is rejected before fraud scoring and posting.

AML and fraud screening. MOD-023 scores the transaction. A high-risk score may result in a hold pending manual review, consistent with the handling of external payments at the same risk level. The score result is recorded in fraud_score_result regardless of outcome.

Atomic double-entry posting. On passing all validation, a single database transaction calls MOD-001 to create the double-entry posting: debit source account, credit destination account. The intra-bank transfer record is updated to posted in the same transaction.

Confirmation and notification. The source account holder receives a debit notification and the destination account holder receives a credit notification via MOD-063 within 10 seconds of the transfer posting.

Integration with batch payments

MOD-135 (batch payment processing) inspects each item in a batch before dispatching to external rails. Items where the destination resolves to an internal account are extracted from the batch and submitted to the intra-bank transfer engine individually. The batch item is marked as settled via intra-bank, and the batch settlement summary distinguishes intra-bank items from external rail items for reconciliation purposes.

Requirements

FR-625 — Routing detection: the system must detect whether a payment destination resolves to an account within the same institution before routing; if it does, the payment must be routed to the intra-bank transfer engine rather than any external rail; this routing decision must be transparent to the customer.

FR-626 — Atomic double-entry execution: intra-bank transfers must be executed as a single atomic double-entry transaction in MOD-001; the transfer must either fully complete or fully fail — partial postings are technically impossible because both the debit and credit are written in the same database transaction.

FR-627 — Validation parity: the system must apply the same pre-payment validation (MOD-020) and transaction fraud scoring (MOD-023) to intra-bank transfers as to external payments; intra-bank status must not be used to bypass or reduce any validation check.

FR-628 — Performance: the system must complete an intra-bank transfer from initiation to both accounts reflecting the updated balance within 5 seconds under normal conditions; the destination account holder must receive a credit notification via MOD-063 within 10 seconds of the transfer posting; these targets apply 24/7/365 with no cut-off window.


Module dependencies

Depends on

Module Title Required? Contract Reason
MOD-001 Double-entry posting engine Required Intra-bank transfers are executed as a single atomic double-entry posting debiting the source account and crediting the destination account in the same database transaction.
MOD-020 Pre-payment validation suite Required Pre-payment validation runs on the source account — available balance, account status, transaction limits — before the transfer is permitted to proceed.
MOD-023 Transaction fraud scorer Required Transaction fraud scoring screens intra-bank transfers using the same model as external payments; intra-bank status does not reduce or bypass fraud checks.
MOD-003 Real-time balance engine Required The available balance of the source account is checked in real time before the transfer is permitted, preventing overdrafts on accounts without an approved overdraft facility.

Required by

(No modules in this wiki currently declare a dependency on this module.)


Policies satisfied

Policy Title Mode How
PAY-001 Payment Operations Policy GATE Intra-bank transfers pass pre-payment validation — available balance, account status, and transaction limits — before posting; the transfer is not posted if the source account has insufficient funds.
AML-007 Sanctions Screening Policy AUTO Intra-bank transfers pass through the same transaction screening as external payments; internal transfers are a known layering typology and screening is not bypassed for intra-bank routing.
PAY-002 Settlement Risk Policy LOG All intra-bank transfers are logged to the payment audit trail with both account IDs, the amount, the initiating channel, and the fraud score result.
CON-005 Fee & Pricing Transparency Policy AUTO The customer is shown both the debit and credit side of the transfer for confirmation before execution, making the immediate book-transfer nature transparent.

Capabilities satisfied

(No capabilities mapped)


Part of SD04 — Payments Processing Platform Compiled 2026-05-22 from source/entities/modules/MOD-141.yaml