AML Screening
AML screening is the regulated process of checking customers, businesses, and transactions against sanctions lists, PEP lists, and adverse-media indices. It is the compliance backbone every fintech platform runs through KYC and beyond.
What AML screening is
AML — Anti-Money-Laundering — screening is the practice of running a customer or transaction against regulator-published lists of high-risk parties. The lists include:
- Sanctions lists — OFAC, UN, EU, UK HM Treasury, and country-specific lists of parties forbidden from transacting in given jurisdictions.
- PEP lists — politically-exposed persons whose government roles or family ties create elevated risk.
- Adverse-media indices — news-derived signals about parties involved in fraud, corruption, or violations.
- Internal blocklists — customers the platform itself has flagged or rejected previously.
AML screening runs at onboarding (inside KYC and KYB flows), at periodic re-screening intervals, and at transaction time when payment behavior triggers a check.
Why fintech platforms need it
Regulators require it. PCI DSS does not directly mandate AML screening, but the Bank Secrecy Act, FinCEN regulations, EU AMLD, and UK’s MLR 2017 do. Platforms that touch money must screen, and the platform’s compliance posture lives or dies by how well screening is integrated.
The other reason is reputational. A platform that processes a sanctioned-party transaction is liable for fines that scale into the millions, plus the operational disruption of the regulator response. AML screening is the cheapest insurance on that risk.
What “good screening” looks like
Production AML screening has four properties:
- Comprehensive list coverage. Every relevant sanctions, PEP, and adverse-media list, refreshed daily, covering the jurisdictions the platform operates in.
- Fuzzy matching. Names match imperfectly across alphabets, transliterations, and diacritics. Production systems use phonetic and edit-distance algorithms tuned for false-positive rates.
- Manual-review workflows. Hits route to compliance analysts with a case-management UI, supporting evidence, and reason codes.
- Audit-grade history. Every check, every match, every analyst decision is retained for the regulator-required period (typically 5–7 years).
Vendors that do this well: ComplyAdvantage, LexisNexis Bridger, Refinitiv World-Check, Onfido (KYC integrated), Sumsub, Persona.
Engineering patterns
A production AML screening service has three integration points:
- Onboarding. Synchronous-with-grace pattern: kick off screening at signup, allow basic actions while it runs, gate higher-risk actions on a clean result.
- Re-screening. Periodic batch jobs (monthly, quarterly) that re-check the existing customer base against updated lists.
- Transaction monitoring. Async event-stream processors that flag transactions matching velocity, geography, or counterparty rules. Operator dashboards surface flagged events to the compliance team.
False-positive management is the engineering team’s biggest day-to-day concern. The rule chain that decides which hits go to which queue is itself a configurable, auditable artifact, and tuning it is an ongoing job.
Code-shape example
The screening boundary that lets vendors be swapped without rewriting the platform:
interface ScreeningInput {
type: "person" | "business";
fullName: string;
dateOfBirth?: string; // person only
registeredAddress?: string; // business only
jurisdiction: string;
externalRef: string; // customer or business id in the platform
}
interface ScreeningHit {
list: "sanctions" | "pep" | "adverse_media";
source: string; // "OFAC SDN", "UN Sanctions", "PEP Tier-1"
matchedName: string;
matchScore: number; // 0..1
evidenceUrl?: string;
raw: Record<string, unknown>;
}
interface ScreeningResult {
externalRef: string;
hits: ScreeningHit[];
outcome: "clear" | "manual_review" | "blocked";
vendorRef: string; // for audit + re-fetch
occurredAt: string;
}
interface AmlVendor {
screen(input: ScreeningInput): Promise<ScreeningResult>;
fetchById(vendorRef: string): Promise<ScreeningResult>;
}
// Decision policy is platform-owned. Vendor returns hits; we decide outcome.
export function decide(hits: ScreeningHit[]): ScreeningResult["outcome"] {
if (hits.some((h) => h.list === "sanctions" && h.matchScore > 0.9)) {
return "blocked";
}
if (hits.length === 0) return "clear";
return "manual_review";
}
// Always log the raw hits, even on "clear", for audit.
export async function runScreening(
vendor: AmlVendor,
input: ScreeningInput,
): Promise<ScreeningResult> {
const result = await vendor.screen(input);
result.outcome = decide(result.hits);
await audit.write({ kind: "aml_screening", ...result });
return result;
}
Decision policy stays in the platform, vendor stays interchangeable, audit log captures every result.
How we implement it at Dashhold
Patterns shipped on every fintech build:
- Onboarding screening as a coordination layer. KYC vendor returns identity-clear, AML screening runs as the next step. We never block the entire UX on AML; basic actions unlock as KYC clears.
- Nightly re-screen of every active customer against updated sanctions and PEP lists. Hits open tickets in the compliance queue automatically.
- Transaction monitoring as event-stream processors (Kafka or similar). Velocity rules, geographic rules, counterparty rules all run as separate processors against the same stream. New rules ship without a redeploy of the platform.
- Compliance queue with structured reason codes. Every hit has a code; every analyst decision picks from a closed set. Analytics teams can measure FP rates per rule.
- Vendor failover on screening calls. Primary vendor (e.g., ComplyAdvantage) fails over to secondary on outage, with clear logging.
- Audit retention as cold storage. Hot tier holds 90 days; cold tier holds 7 years. Both queryable via the compliance UI.
Common pitfalls
- No fuzzy matching tuning. Default vendor settings are usually too strict, producing high false-positive rates that drown analysts. Tune.
- Vendor lock-in via deeply embedded SDK calls. Wrap the vendor in an interface from day one. Switching vendors is otherwise a multi-month project.
- No re-screening cadence. Sanctions lists update daily. Without scheduled re-screens, the platform’s compliance posture decays silently.
- Treating transaction monitoring as a downstream concern. It is part of the platform. Moving it out into a separate vendor’s UI produces a fractured compliance story.
- Skipping the audit log on “clear” outcomes. Auditors want to see every check, including the ones that came back clean. Log everything.
- Manual review without structured reason codes. Free-text reasons become noise within a quarter. Use a closed enum and let compliance own the list.
Where AML screening fits
AML screening is woven through every payment platform. It appears in KYC onboarding, in KYB onboarding, in payout-time checks, and in transaction-time monitoring. Treating it as one capability rather than three separate integrations is how fintech engineering teams keep their compliance posture coherent — and how the studio’s fintech development practice builds it.
See also
- KYC onboarding — where AML screening runs at signup
- KYB onboarding — where AML screening runs on businesses and UBOs
- Payment platform — the broader system AML protects