Fraud Detection with Knowledge Graphs: Uncovering Rings, Loops, and Anomalies
Why Graphs for Fraud Detection?
Traditional fraud detection relies on rule-based systems and machine learning on tabular data — flagging transactions above a threshold, detecting unusual login locations, or scoring credit applications with logistic regression. These approaches work well for individual bad actors. They fail against organised fraud: collusion rings, synthetic identity networks, circular money laundering, and account takeover cascades.
Fraud rings are fundamentally graph structures. A shared phone number across fifty accounts isn't a column value — it is a connection. A chain of transactions that cycles back to the origin isn't a set of rows — it is a directed cycle. A fraudster controlling multiple synthetic identities isn't a pattern in any single table — it is a star-shaped subgraph of shared attributes.
Property graphs capture these relational patterns natively. Every transaction, device fingerprint, IP address, phone number, and account becomes a node. Every relationship — SENT, USES_DEVICE, SHARES_IP — becomes an edge. Once your data lives in a graph, the algorithms that detect fraud become graph algorithms. This article walks through a complete fraud detection pipeline using Neo4j and its Graph Data Science (GDS) library.
Graph Data Model for Financial Fraud
The foundation of any graph-based fraud system is the data model. Every entity that can be shared or connected across accounts becomes a node. Every connection becomes a relationship.
Core entities:
| Entity | Description | Example Properties |
|---|---|---|
Customer | Account holder or business | id, name, createdAt, riskScore |
Transaction | Financial transfer | amount, currency, timestamp, status |
Device | Browser or mobile fingerprint | fingerprint, deviceType, os |
IPAddress | Network origin | address, asn, country |
PhoneNumber | Contact number | number, carrier, isPrepaid |
Address | Physical location | street, city, postcode, country |
Relationships:
// Financial flows
(c1:Customer)-[:SENT {amount, timestamp, currency}]->(t:Transaction)
(t:Transaction)-[:RECEIVED_BY]->(c2:Customer)
// Shared attributes (fraud indicators)
(c:Customer)-[:USES_DEVICE {firstSeen, lastSeen}]->(d:Device)
(c:Customer)-[:USES_IP {firstSeen, lastSeen}]->(ip:IPAddress)
(c:Customer)-[:HAS_PHONE]->(p:PhoneNumber)
(c:Customer)-[:HAS_ADDRESS]->(a:Address)
A shared device between two accounts that otherwise have no connection is a strong fraud signal. In a relational database, detecting this requires joining through a device-account intersection table. In Cypher, it is a single traversal:
MATCH (fraud:Customer {id: $fraudId})-[:USES_DEVICE]->(d:Device)
<-[:USES_DEVICE]-(suspected:Customer)
WHERE suspected.id <> $fraudId
RETURN suspected.id AS accountId,
d.fingerprint AS deviceFingerprint,
d.firstSeen AS deviceFirstSeen
This query executes in milliseconds on graphs with billions of nodes when backed by an index on :Customer(id).
Detecting Fraud Rings with Cypher
Circular Transaction Loops
Money laundering frequently involves circular flows: A sends to B, B sends to C, C sends back to A. In a graph, this maps naturally onto a directed cycle of length three or more.
// Detect 3-step money laundering cycles
MATCH p = (a:Customer)-[:SENT]->(t1:Transaction)-[:RECEIVED_BY]->(b:Customer)
-[:SENT]->(t2:Transaction)-[:RECEIVED_BY]->(c:Customer)
-[:SENT]->(t3:Transaction)-[:RECEIVED_BY]->(a)
WHERE a.id < b.id AND b.id < c.id
AND t1.amount > 10000
AND t2.amount > 10000
AND t3.amount > 10000
AND t1.timestamp <= t2.timestamp
AND t2.timestamp <= t3.timestamp
RETURN a.id, b.id, c.id,
t1.amount + t2.amount + t3.amount AS totalCirculated,
duration.between(t1.timestamp, t3.timestamp).hours AS cycleDurationHours
ORDER BY totalCirculated DESC
LIMIT 50
The a.id < b.id AND b.id < c.id guard prevents duplicate permutations of the same cycle. This pattern extends naturally to four-step and five-step cycles by adding more segments.
Shared Attribute Star Detection
Synthetic identity fraud creates accounts that share a small set of attributes — the same phone number, device, and address — while appearing unrelated in the financial flow graph. This forms a star topology.
// Find IP addresses shared by an unusually high number of accounts
MATCH (c:Customer)-[:USES_IP]->(ip:IPAddress)
WITH ip, count(c) AS accountCount
WHERE accountCount > 5
MATCH (c:Customer)-[:USES_IP]->(ip)
RETURN ip.address AS sharedIP,
accountCount,
collect(c.id)[..10] AS sampleAccounts,
collect(DISTINCT c.riskScore) AS riskScores
ORDER BY accountCount DESC
A single IP address shared by ten accounts, where those accounts have different addresses and phone numbers, is worth immediate investigation. When combined with a prepaid phone number and a newly created device fingerprint, it becomes a near-certain fraud indicator.
Applying GDS Algorithms for Fraud Scoring
Cypher queries catch known patterns. Graph Data Science algorithms catch unknown patterns by scoring every node and community in the graph.
Pipeline Overview
The typical GDS fraud pipeline has four stages:
- Project a graph view — select relevant nodes and relationships into an in-memory graph
- Run algorithms — PageRank, Betweenness Centrality, Louvain Community Detection
- Write results — persist scores as node properties
- Query the enriched graph — use scores in risk models
Graph Projection
CALL gds.graph.project(
'fraud-graph',
'Customer',
{
SENT: { orientation: 'UNDIRECTED' },
USES_IP: { orientation: 'UNDIRECTED' },
USES_DEVICE: { orientation: 'UNDIRECTED' }
}
)
Using UNDIRECTED orientation for shared-attribute edges makes the graph topology symmetric — important for community detection algorithms that do not consider edge direction.
PageRank for Influence Scoring
Fraudsters who control many synthetic accounts will naturally become high-PageRank nodes, because their synthetic accounts all connect to shared infrastructure (devices, IPs, phones) that they also connect to.
CALL gds.pageRank.write('fraud-graph', {
maxIterations: 100,
dampingFactor: 0.85,
writeProperty: 'fraudPageRank'
})
Accounts with a fraudPageRank in the top 1% of the distribution, combined with a recent creation date, are candidates for manual review.
Louvain for Community Detection
Legitimate customers form small, dense communities (family groups, colleagues, neighbours). Fraud rings also form dense communities — but with a distinctive signature: high internal connectivity combined with few external connections.
CALL gds.louvain.write('fraud-graph', {
maxLevels: 5,
writeProperty: 'communityId'
})
// Find suspiciously small, dense communities
MATCH (c:Customer)
WITH c.communityId AS communityId,
count(c) AS communitySize,
collect(c.fraudPageRank) AS pageRanks
WHERE communitySize >= 3 AND communitySize <= 20
RETURN communityId,
communitySize,
apoc.coll.percentiles(pageRanks, [50, 90]) AS pageRankPercentiles
ORDER BY communitySize ASC
LIMIT 20
A community of 5–20 accounts with a shared device, high internal PageRank, and no transaction history among members is a textbook synthetic identity ring.
Graph vs Traditional Fraud Detection
| Dimension | Rule-Based / ML | Graph-Based |
|---|---|---|
| Data model | Flat tables, feature vectors | Property graph with typed edges |
| Collusion detection | Requires engineered pair features | Natural via shared-attribute traversal |
| Novel fraud patterns | Requires retraining | Zero-day detection via graph structure |
| Synthetic identity | Hard — identical features blend in | Easy — star patterns are directly visible |
| Circular laundering | Impossible without graph traversal | Trivial cycle detection in Cypher |
| Explainability | Black-box model scores | Traversable evidence paths |
| Real-time scoring | Yes, with feature store | Hybrid — rules for RT, GDS for batch |
Production Considerations
Incremental vs Batch Scoring
GDS algorithms like PageRank and Louvain operate on static snapshots. In a fraud context where new transactions arrive every second, two complementary strategies exist:
- Micro-batch scoring: run GDS every N minutes on a sliding time window (last 30 days of activity). This catches emerging rings within minutes.
- Hybrid approach: Cypher queries and lightweight rules handle real-time flagging (shared device check, velocity checks); GDS runs periodic deep scans (hourly or daily).
Most production deployments use both: fast Cypher checks at request time, periodic GDS scoring for deep analysis.
Feature Store Integration
Graph-derived scores — PageRank, community ID, shared-attribute count — become features in your broader ML pipeline. Export them to your feature store (Feast, Tecton) so that real-time inference models consume them alongside tabular features.
# Example: Export PageRank scores to a feature store
import neo4j
from feast import FeatureStore
driver = neo4j.GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))
records, _, _ = driver.execute_query(
"MATCH (c:Customer) RETURN c.id AS customer_id, c.fraudPageRank AS page_rank"
)
store = FeatureStore(repo_path="./feature_repo")
store.write_to_online_store(
feature_table="customer_graph_features",
df=pd.DataFrame.from_records(records)
)
Graph Size Management
A fraud graph for a mid-sized fintech can reach 100M+ nodes and 1B+ relationships. Mitigations include:
- Time-windowed projections: run GDS only on the last 30–90 days of activity
- Node filtering: exclude dormant accounts (no activity in 6+ months) from projections
- Sampling: for exploratory analysis, project a random sample and extrapolate findings
Temporal Decay
A shared IP address from 2018 is far less suspicious than one shared last week. Model temporal edges with weight properties that decay with age, or restrict projections to recent windows.
// Weight edges by recency — more recent = higher weight
MATCH (c:Customer)-[r:USES_IP]->(ip:IPAddress)
SET r.weight = exp(-duration.between(r.lastSeen, date()).days / 30.0)
This exponential decay halves the weight every 21 days, ensuring old shared attributes contribute little to algorithm scores.
Conclusion
Fraud is fundamentally relational. Organised fraud rings, synthetic identity networks, circular money laundering, and coordinated bot attacks all produce graph structures that are invisible in tabular data. By modelling your fraud domain as a property graph and applying graph algorithms — community detection, centrality scoring, and cycle detection — you can detect these patterns directly.
The combination of Neo4j's Cypher query language for pattern matching and the GDS library for scalable algorithm execution provides a complete toolkit for graph-powered fraud detection. When integrated with existing ML pipelines through feature stores, graph signals can lift fraud detection performance by 20–40% in production deployments — particularly for the collusion and synthetic identity cases that traditional models miss.
For teams starting out: model your data as a graph first, even if you only run Cypher queries. The act of connecting accounts through shared devices, IPs, and transaction flows will reveal fraud patterns that no feature engineering on flat tables can match. Add GDS algorithms once your graph reaches a scale where manual querying becomes impractical — by that point, you will already have the evidence that graph is the right model for the job.