AML name screening is the step where you compare a customer's name — and whatever else you know: date of birth, country, document numbers — against sanctions and watch lists, and decide whether a hit needs review. It sounds like a string comparison. It is not, and most failures come from treating it like one.
What the lists actually contain
The four official consolidated lists we load — OFAC SDN and Consolidated, EU, UK and UN — hold about 33,000 records and 100,000 names, because a single record carries aliases. OFAC marks each alias strong or weak; the EU flags every alias with a strong attribute; the UK publishes non-Latin spellings separately. A tool that indexes only the primary name discards most of the material the publisher gave you.
Why exact match fails
Three reasons, in order of frequency. Transliteration: the same person is «Владимир Путин» in a Russian document, Vladimir Vladimirovich PUTIN on the OFAC list and Vladimir Vladimirovitj PUTIN on the EU list. Word order and particles: «AL-ZAWAHIRI, Aiman» versus «Ayman al Zawahiri». Typos in your own data: a customer typed «Zawahri». An exact-match screen returns nothing for all three; a regulator will not accept "the string did not match" as a defence.
Fuzzy versus dictionary matching
Fuzzy matching (edit distance, trigrams, phonetics) handles typos and light transliteration differences. It does not connect «Ким Чен Ын» to Jong Un KIM, because the Russian rendering of a Korean name and the English one share almost no letters. That needs a dictionary of name parts across scripts — the approach used by OpenSanctions' logic-v2 scorer, which KYCWire runs. In our public test set, dictionary symbols are what turn the cross-script cases from misses into 0.95 matches.
Supporting facts change the score, not the candidate
A good engine uses date of birth, gender and country as penalties: a same-name candidate born in a different year scores lower, but is still shown. Hiding it would be a false negative you cannot audit. In KYCWire every match carries a features object that says which signal moved the score.
Three numbers to demand from any vendor
- Recall on a published test set — the share of listed names the engine finds when queried with aliases, typos and other scripts. Ours: recall@5 of 0.99 on 400 cases, published on the methodology page with the failures listed.
- False «likely» rate on names that are not listed — how often a clean name gets a high-confidence hit. Ours: 0 of 15 negatives.
- List freshness — hours between the publisher's update and yours, and whether a failed refresh silently keeps stale data. Ours: 6-hour refresh, version shown in every response, failed refresh keeps the last good version and alerts.
What to store
For each check: the query, the list versions it ran against, the candidates and scores, and the reviewer's decision. That is the audit trail. KYCWire writes the first four automatically (audit trail API, CSV export); the decision is yours to record.



