Fraud Detection with Graph Databases: Patterns, Algorithms, and Production Architectures
Why Graphs for Fraud Detection?
Fraud is fundamentally relational. A synthetic identity shares a phone number with a known bad actor. A credit card is used at a merchant that sits two hops from a flagged money mule. A set of accounts all registered from the same IP address, using the same device fingerprint, forming a connected component that no single rule can isolate.
Traditional fraud detection relies on rules engines and machine learning models operating on flat feature vectors. These systems are good at scoring individual transactions, but they systematically miss relational fraud — patterns that only become visible when you examine the connections between entities. A transaction that looks legitimate in isolation may reveal itself as fraudulent when viewed in the context of the network around it.
Graph databases are purpose-built for this problem. By storing entities as nodes and their interactions as relationships, they enable queries and algorithms that surface fraud patterns no tabular model can express.
The Four Fundamental Fraud Patterns
Most graph-based fraud detection reduces to four structural patterns. Each maps to a specific graph algorithm or query pattern.
Pattern 1: Rings and Cycles
Fraud rings form closed loops. Money laundering, voucher abuse, and fake review rings all produce cyclic transaction patterns where value circulates among a set of accounts without ever leaving the cluster.
// Detect simple cycles of length 3-5 in a money transfer graph
MATCH path = (a:Account)-[:TRANSFERRED_TO]->(b:Account)-[:TRANSFERRED_TO]->(c:Account)-[:TRANSFERRED_TO]->(a)
WHERE a.id < b.id AND b.id < c.id
RETURN a.id, b.id, c.id,
duration.between(a.created_at, c.created_at).days AS cycle_duration
LIMIT 100
This is a directed cycle of length three. In practice, fraud rings are longer and often involve layering — accounts that alternate between legitimate-looking transactions and suspicious transfers. The Neo4j GDS library's native cycle detection or a series of variable-length path queries can uncover these structures at scale.
Pattern 2: Shared Identity (Entity Resolution)
Synthetic identity fraud creates multiple accounts that share identifiers — phone numbers, email addresses, device fingerprints, or IP addresses — while changing names and dates of birth. A graph query that groups accounts by shared identifiers is often the fastest way to collapse synthetic identities.
// Find accounts sharing multiple identifiers - a strong fraud signal
MATCH (a:Account)-[:USES]->(i:Identifier)<-[:USES]-(b:Account)
WHERE a.id < b.id
WITH a, b, collect(DISTINCT i.type) AS shared_types, count(*) AS shared_count
WHERE shared_count >= 3
RETURN a.id AS account_a, b.id AS account_b, shared_types, shared_count
ORDER BY shared_count DESC
When three or more identifiers overlap between two otherwise unrelated accounts, the probability of synthetic identity fraud rises dramatically. This is a query that is trivial in Cypher and nearly impossible to express efficiently in SQL without a fixed number of joins.
Pattern 3: Proximity to Known Bad Actors
Link analysis assigns risk based on graph distance. If an entity is within two hops of a confirmed fraudster, the risk profile changes. This is the pattern behind many alert triage systems.
// Score entities by proximity to known bad actors
MATCH (bad:Entity {is_flagged: true})
MATCH (target:Entity)
WHERE target.is_flagged = false
MATCH path = shortestPath((bad)-[:HAS_PHONE|HAS_EMAIL|TRANSACTED_WITH*..3]-(target))
RETURN target.id,
length(path) AS distance_to_risk,
bad.id AS proximate_bad_actor
ORDER BY distance_to_risk ASC
The distance threshold matters. Two hops is the default for most systems — one hop is a direct relationship (high risk), two hops introduces plausible deniability but still meaningful association. Beyond three hops, the signal weakens significantly.
Pattern 4: Anomalous Community Structure
Fraudsters operating in collusion form dense subgraphs — clusters of accounts that interact primarily with each other and rarely with the broader network. Community detection algorithms like Louvain and Label Propagation naturally surface these clusters.
// Run Label Propagation to find suspicious communities
CALL gds.labelPropagation.stream('fraud-graph')
YIELD nodeId, communityId
WITH gds.util.asNode(nodeId) AS node, communityId AS community
MATCH (node)-[:TRANSFERRED_TO]-()
WITH community, count(DISTINCT node) AS member_count,
collect(DISTINCT node.id) AS members
WHERE member_count < 20 AND member_count > 3
RETURN community, member_count, members
ORDER BY member_count DESC
Small, dense communities with high internal transaction volume and little external connectivity are textbook fraud rings. The community detection approach scales to millions of nodes and surfaces rings that no fixed-depth query can reach.
Production Architecture for Graph-Based Fraud Detection
A production fraud detection system using graph databases typically spans three layers:
| Layer | Technology | Responsibility |
|---|---|---|
| Ingestion | Kafka / Kinesis → Neo4j | Stream transactions, enrich entities, maintain temporal state |
| Detection | Neo4j + GDS + ML | Cypher queries, graph algorithms, feature extraction for ML models |
| Response | Rules engine + case management | Alert generation, manual review, automated block/allow decisions |
Batch vs Real-Time
Graph-based fraud detection operates on two time scales:
-
Batch (hourly/daily): Community detection, PageRank scoring, entity resolution across the full graph. These algorithms are computationally expensive and run on graph projections, not the live operational graph.
-
Real-time (sub-second): Proximity queries, shared identity checks, and entity resolution lookups. These are Cypher queries with index-backed lookups that return in milliseconds.
// Real-time fraud check at transaction time
// Returns risk score based on 2-hop proximity to flagged entities
MATCH (sender:Account {id: $sender_id})
OPTIONAL MATCH (sender)-[*1..2]-(flagged:Entity {is_flagged: true})
WITH sender, count(DISTINCT flagged) AS proximity_flags
OPTIONAL MATCH (sender)-[:USES]->(id:Identifier)<-[:USES]-(other:Account)
WITH sender, proximity_flags, count(DISTINCT other) AS shared_id_count
RETURN sender.id,
CASE
WHEN proximity_flags > 2 THEN 'HIGH'
WHEN proximity_flags > 0 THEN 'MEDIUM'
WHEN shared_id_count > 2 THEN 'MEDIUM'
ELSE 'LOW'
END AS risk_level,
proximity_flags,
shared_id_count
This single query replaces what would require six to ten relational JOINs or API calls, and it completes in single-digit milliseconds with appropriate indexes on Account.id and the is_flagged property.
Graph Algorithms for Fraud Detection
The Neo4j GDS library provides algorithms that map directly to fraud detection use cases:
| Algorithm | Fraud Use Case | Complexity |
|---|---|---|
| PageRank | Score entities by influence — fraudsters often have unusual centrality patterns | O(E) |
| Betweenness Centrality | Identify bridge entities used for layering | O(VE) |
| Louvain / Leiden | Discover fraud communities and rings | O(n log n) |
| Label Propagation | Large-scale community detection for collusion | Near-linear |
| Node Similarity | Find accounts with overlapping identifiers | O(n²) |
| K-Component Detection | Find strongly connected fraud rings | Polynomial |
A common production pattern is to run PageRank and community detection on your full transaction graph nightly, then persist the scores as node properties for real-time lookups.
// Write PageRank scores back to the graph for real-time use
CALL gds.pageRank.write('fraud-graph', {
writeProperty: 'fraud_centrality',
maxIterations: 40,
dampingFactor: 0.85
})
Graph Data Modeling for Fraud
Your graph schema determines what fraud patterns you can detect. Here is a minimal but production-proven model:
Nodes:
Account— customer accounts, wallets, or user profilesTransaction— individual events (promoted to node for temporal properties)Identifier— phone numbers, emails, device IDs, IP addressesMerchant— counterparties in transactions
Relationships:
[:TRANSFERRED_TO {amount, timestamp}]— between Accounts (or Account→Merchant)[:USES]— between Account and Identifier[:SHARES_DEVICE]— between Accounts on the same device
Promoting transactions to nodes (rather than making them relationships) is a deliberate choice. It allows attaching multiple relationships to a transaction — linking it to accounts, merchants, risk scores, and review outcomes — and enables temporal queries like "find all transactions from this account in the last hour."
// Create a time-indexed transaction with fraud signal
CREATE (tx:Transaction {
id: $tx_id,
amount: $amount,
timestamp: datetime($timestamp),
currency: $currency,
channel: $channel
})
CREATE (sender:Account {id: $sender_id})
CREATE (recipient:Account {id: $recipient_id})
CREATE (sender)-[:SENT {timestamp: datetime($timestamp)}]->(tx)
CREATE (tx)-[:RECEIVED_BY {timestamp: datetime($timestamp)}]->(recipient)
Measuring What Matters
Graph-based fraud detection introduces new metrics alongside traditional ones:
| Metric | What It Measures |
|---|---|
| Connected component size | Scale of potential fraud rings |
| Graph distance to known fraud | Proximity risk distribution |
| Community density | Internal vs external edge ratio |
| Shared identifier overlap | Entity resolution confidence |
| Cycle count | Prevalence of circular flows |
A well-tuned graph fraud system typically catches 2–5x more relational fraud than rules-only systems while maintaining the same false-positive rate. The most significant gains come in synthetic identity detection and collusion rings — patterns that are structurally invisible to feature-based models.
When Graphs Are Not the Answer
Graph databases excel at relational fraud, but they are not a replacement for all fraud detection techniques:
- Transaction velocity checks (too many transactions in a short window) are better served by counters and time-series databases.
- Anomaly detection on individual features (unusual amounts, geographic mismatches) is best handled by traditional ML models.
- Deep learning on sequence data (card-not-present fraud patterns) benefits from recurrent or transformer architectures.
The most effective fraud detection architectures are hybrid: a graph database for relational patterns, a rules engine for deterministic checks, and ML models for feature-based scoring — all feeding into a unified risk decision. The graph layer fills the gap that the other two cannot reach: the structure of the network itself.
Further Reading
- Graph Algorithms with Neo4j GDS — Deep dive into PageRank, community detection, and centrality
- Community Detection Algorithms — Louvain, Leiden, and Label Propagation in production
- Graph Data Modeling with Neo4j — Schema design patterns for fraud domains
- Knowledge Graphs for Vulnerability Prioritisation — Graph-based risk scoring in security contexts