AML transaction monitoring and held states
Funds arrive but stay in escrow until compliance clears the transaction.
By Solomon Ajayi · Free to read, no signup
A user attempts a ₦1,000,000 deposit. Your AML rules trigger, the source jurisdiction is on a high-risk list, the amount is unusual for this user's history, or the pattern resembles structuring. The cash physically arrives in your FBO account at the sponsor bank (you can't stop the wire), but you do NOT credit the user's wallet. The funds sit in an 'AML Held' liability while your compliance team investigates. Days or weeks later, compliance either CLEARS (release to user) or ESCALATES (file SAR with regulator, funds stay held indefinitely pending guidance). The ledger trail is the regulatory evidence, exactly what the regulator's first question will demand.
When AML rules flag a deposit, you face a physical fact you cannot undo: the wire already landed in your FBO at the sponsor bank, and you cannot bounce it back. What you can control is whether the user gets to use it. So the cash arrives, the FBO grows, but you do not credit the user's wallet. The money goes into an AML Held liability and waits while compliance investigates the source.
From the user's side the deposit simply reads as processing; from the regulator's side, the ledger records the exact second the funds entered escrow. When compliance clears the deposit, you move it from AML Held into the user's wallet, and the FBO never budges, because the cash sat at the bank the whole time, only its classification on your books changed. If compliance escalates instead, that release entry never fires: you file a suspicious activity report and the funds stay held, possibly indefinitely, pending the regulator's guidance.
The point of doing this at the ledger is the gap between the held timestamp and the release timestamp; that gap is your audit trail. Compliance is not about having rules, it is about being able to prove, after the fact, exactly when funds were held, who reviewed them, and what was decided. A regulator's first question is when did you know, and a ledger answers it with a SQL statement instead of a frantic search through application logs.
Worked example, step by step
₦1,000,000 deposit arrives, AML trips, held in escrow
Wire from a flagged jurisdiction. Your AML engine triggers (high amount + high-risk source). The cash arrives in your FBO (the sponsor bank doesn't see your AML state), but you do NOT credit the user. The funds go straight to an AML-held liability while compliance reviews.
| Account | Debit | Credit |
|---|---|---|
| FBO at Sponsor Bank (1300) | ₦1,000,000.00 | |
| AML Held Funds (2300) | ₦1,000,000.00 |
FBO UP ₦1,000,000, the cash is physically there. AML Held Funds UP ₦1,000,000, the offsetting liability. User Wallet UNCHANGED, the user sees nothing in their app. From the user's perspective, the deposit is 'processing.' From the regulator's perspective (if they ever ask), the ledger shows the exact second the funds landed in escrow.
Compliance clears after 5 days, release to user wallet
Compliance officer reviews the user's KYC, source-of-funds documentation, and transaction history. Cleared. Move the funds from AML Held into the user's wallet.
| Account | Debit | Credit |
|---|---|---|
| AML Held Funds (2300) | ₦1,000,000.00 | |
| User Wallet (2000) | ₦1,000,000.00 |
AML Held Funds DOWN ₦1,000,000. User Wallet UP ₦1,000,000. The user now sees the deposit. FBO UNCHANGED, the cash never moved at the bank level, only the classification on your books shifted. The 5-day timestamp gap is your audit trail. If compliance had ESCALATED instead, this entry would never have fired and you'd file a SAR with regulators; the funds would stay in AML Held pending regulator guidance, possibly forever.
Takeaway
AML monitoring is the difference between 'we comply' and 'we can prove we comply.' The pattern: funds arrive in FBO → triggered amounts land in a held liability → compliance reviews → release or escalate. The ledger trail (when held, when reviewed, by whom, outcome) is the evidence regulators demand. Most fintechs build this in app code (rules engine + flags). The mature ones build it AT THE LEDGER LEVEL so every regulator query can be answered with a SQL statement. CBN, FCA, FinCEN all care about this; lack of it is how unlicensed operations get shut down.
Practice this on a real ledger
Reading is half of it. Open this lesson in the lab to post the entries yourself against a real Postgres-backed double-entry ledger, with the validation on. Free, your sandbox is yours.