Ring detection · graph analysis 2026

Making fraud rings visible in a whole population

Groups of accounts working together are invisible one at a time. Drawn as a map of who is connected to whom, they stand out as clusters. Real customers do not get dragged in with them.

Business Analyst, AWS Payments & Fraud Prevention

Impact

Tested against a group already confirmed by hand, the map put every one of its members in a single cluster. Something invisible one account at a time became a group an analyst could act on in minutes. It then scaled from one region to the multi-million-account global population.

Whole-population relations graph
100% of a known ring in one cluster
flagged ring legitimate broker
Hover any dot to isolate the group it belongs to. Toggle to hide the ordinary customers and leave only the suspicious groups. Representative shape. The live version runs on confidential data.

A line means two accounts share something meaningful, weighted by how rare that thing is and how strongly it actually predicts fraud. The larger dots are the accounts that bridge two groups, which are often the ones worth acting on first.

What a shared signal is worth as an edge
  • Rare shared hard signal
    informative
  • Shared IP range
    tells you little
  • Shared phone format
    tells you little
  • Shared BIN range
    tells you little
Illustrative weights. The live scores run on confidential data. What is real is that simply counting shared details would treat all four of these as equally meaningful.

The three context bars are deliberately equal. The finding was that they sit near the base rate, not that one outranks another.

Show the data table
What a shared signal is worth as an edge: ranked.
CategoryValueNote
Rare shared hard signalinformativeRare, and far more common among fraudsters than among everyone else. These are the connections the clusters are built from.
Shared IP rangetells you littleReal customers share IP ranges by chance all the time, so on its own this means almost nothing.
Shared phone formattells you littleThe same format repeats across unrelated real accounts. Checking which identifiers are trustworthy is exactly what stops this creating fake groups.
Shared BIN rangetells you littleThousands of real customers share a card issuer and have nothing else to do with each other.
Context

Coordinated abuse hides in the gaps between accounts. One account at a time, a ring is invisible. As a graph it is a dense knot in an otherwise sparse field. The catch is that naive linking on a shared IP or a shared phone format also ties together thousands of unrelated legitimate customers, so a careless graph just draws one giant useless blob.

What I did
  • I built a whole-population fraud-relations graph explorer: a Python backend that loads the full account population, builds a two-tier hard/soft relationship graph, and renders it client-side over WebGL.
  • I designed the edge-confidence model that makes the graph work: an information-retrieval weighting of excess purity over base rate × IDF, tuned for a fraud-dense population where plain shared-attribute counting is worthless.
  • I then ran a key-reliability audit that removed the identifiers which would have falsely linked legitimate accounts.
  • I layered the ring-finding on top of it, so components surface the rings, sub-communities split them, and centrality flags the brokers bridging two rings.
  • I re-pointed the graph engine at the global payments-fraud cluster with a windowed population rebuild so it holds at multi-million-account scale.
Outcome

An analyst acts on a whole cluster instead of working the members separately, and the brokers bridging two rings surface as a finding of their own. I validated the graph against a known ring held as ground truth before trusting any cluster it drew, and the key-reliability audit kept legitimate look-alikes out.

Without this work

Rings stay hidden in pairwise queries. Analysts chase individual members and miss the brokers bridging rings entirely. Any naive linking graph would have swept thousands of legitimate customers into the same clusters, trading invisible fraud for false accusations.

The full story

A ring is invisible one account at a time and obvious as a graph. Getting from the first view to the second is the entire problem, because a graph naive enough to link on any shared attribute links half the legitimate population together.

So the work was not the rendering. It was the edges. In a fraud-dense population, “these two accounts share an attribute” means almost nothing: plenty of legitimate customers share IP ranges, phone formats, and BIN ranges by chance. I weighted every candidate edge by how much more purely it predicts co-fraud than the base rate would, scaled by how rare, and therefore how informative, the shared signal is. In IR terms, that is an excess-purity × IDF score.

With trustworthy edges the graph mechanics follow, and the payoff is the broker: the high-betweenness account bridging two rings, which no pairwise query would ever return. The frontend draws the whole population over WebGL with hover-isolation, a weighted shortest-path trace between any two accounts, and one-click legitimate-impact and bulk-close SQL per cluster.

Validation mattered more than visuals. On a ring I had already confirmed, the graph placed 100% of its members in a single component. Getting there took twelve documented iterations, each recorded with its source and its verification: edge tiers reworked, the soft tier gated so a weak signal could not stand as an edge on its own, shared-NAT addresses discounted so one egress point could not fabricate a ring, and unreliable identifiers deleted outright rather than quietly down-weighted. That last choice is the one that matters, because every cluster ships with bulk-close SQL attached. A bad edge here does not produce a bad chart. It closes a real customer’s account.

  • Graph analysis
  • sigma.js / WebGL
  • Community detection
  • Betweenness
  • Ring detection