Writing

Sanctions: the match that must never be missed

Screening a name is a matching problem with a brutal asymmetry. Miss a real match and the cost is not a wasted minute.

Enso Intelligence · Dhaka/June 19, 2026 · 6 min

A name that does not sit still

A sanctions screen begins with something deceptively simple: a name on a transaction, checked against a list of sanctioned parties. If it were really that simple, a string comparison would solve it. It is not simple, because names do not sit still. The same entity appears as "Mohammed," "Muhammad," and "Mohamed." A company is written with and without its legal suffix, transliterated from another alphabet three different ways, abbreviated, misspelled, or deliberately altered by someone who would prefer not to be found. The list has aliases, known variations, partial names. The match you are looking for is rarely an exact one, and the party most worth catching is the one trying hardest not to match.

So screening is not a lookup. It is a matching problem over messy text, and matching problems have a dial. Turn it toward strictness and you only catch exact matches, missing the variants. Turn it toward looseness and you catch the variants along with a flood of false hits that bury the real ones. Where you set that dial is not a tuning preference. It is a decision about which kind of error you are willing to make.

The asymmetry that sets the dial

The two errors are not equal. A false hit, flagging a party who turns out to be clear, costs a compliance officer a few minutes to dismiss. A missed match, clearing a party who is actually sanctioned, is a violation, with penalties, enforcement, and reputational damage attached. One error wastes time. The other is the entire risk the screen exists to prevent.

When the errors are that lopsided, the design is forced. You build toward catching the real match even at the cost of more false hits, because false hits are recoverable and missed matches are not. And you structure the matching in tiers rather than a single threshold. An exact match is a hit. A match after normalizing both names to a standard form is a hit. A close fuzzy match above a high similarity threshold is a probable hit, surfaced for review. A weaker similarity is a possible match, also surfaced, never silently dismissed. The dial is not one setting. It is a graded ladder, and the lower rungs route to a human rather than to a decision.

{
  "decision": "review",
  "rule_family": "SANCTIONS",
  "match": {
    "input": "ACME Trading FZE",
    "matched_to": "ACME Trading (F.Z.E.)",
    "list": "OFAC SDN",
    "method": "normalized_then_fuzzy",
    "score": 0.91
  },
  "message": "Probable match to a listed party after name normalization. Do not proceed; route to sanctions compliance for disposition.",
  "checked": true
}

The screen does not declare a violation on a fuzzy match. It declares a probable match and hands it up, because the judgment of whether a 0.91 similarity is the same entity belongs to a person. What the screen guarantees is that the match was not missed.

Fail closed, because the gap is the violation

The most important behavior is what happens when the screen cannot run. The list is briefly unreachable. A name cannot be resolved to anything. The data is incomplete. The tempting response, the one that keeps a queue moving, is to treat "no match found" as "clear." That is exactly the false clear the whole system exists to prevent, because "no match found" and "could not check" are different statements, and only one of them is safe.

So a sanctions screen fails closed. When it cannot complete the check, it does not report the party as clear. It reports that screening could not be completed, and the transaction holds for review. A party you could not screen is not a party you have cleared. In sanctions more than anywhere, silence is not a clean result. It is an unchecked one, and an unchecked party is precisely how a sanctioned one gets through.

The point

Sanctions screening is the clearest case that a lookup and a decision are different things. The names are messy, the right match is usually inexact, and the party worth catching is the one disguising itself. The asymmetry between a false hit and a missed match dictates the entire design: graded matching that errs toward catching, fuzzy matches routed to people rather than dismissed, and a hard refusal to treat "could not check" as "clear." Get any of that wrong and the screen looks like it is working right up until the one match it should have caught is the one it quietly let pass.