Fraud & Financial Crime Intelligence
Find the ring, not just the transaction — graph-native detection that traces the shared devices, accounts, and identities a rules engine never connects.
Rules engines score transactions one at a time, so a ring that spreads a scheme across fifty accounts never trips a threshold. The evidence that exposes fraud lives between the records — a shared device, a recycled phone number, a common beneficiary — and in relational SQL every additional hop is another expensive join.
We model fraud as what it actually is: a graph. Modern Graph SQL — SQL/PGQ in the SQL:2023 standard, and the GQL standard published in 2024 — lets us write graph pattern-matching queries inside the SQL environment your team already runs, so multi-hop traversal stops being a join explosion. Entity resolution collapses duplicate identities, community detection surfaces the rings, and scoring runs on streaming data so the decision lands before the money does.
- Fraud graph model — entities, shared identifiers, relationships
- Graph SQL query layer (SQL/PGQ, GQL, openCypher)
- Entity resolution & identity deduplication pipeline
- Ring detection — community detection and centrality scoring
- Real-time scoring on streaming transactions (Kafka / Flink)
- Investigator tooling — case views and link analysis
Fraudsters do not operate alone. Neither should your queries.
Fraud detection is fundamentally a graph problem, because fraudsters rarely operate in isolation — they inevitably share identifiers: devices, bank accounts, phone numbers, addresses, beneficiaries. Tracing those connections with standard relational SQL means chaining expensive JOIN operations across tables, and the cost compounds with every hop. Modern Graph SQL lets you write graph pattern-matching queries directly inside a SQL environment, so a four-hop question stays one readable query — no separate graph silo, no parallel ETL, no second team.
-- Relational: every hop is another join
SELECT DISTINCT ring.account_id
FROM accounts AS flagged
JOIN device_use AS d1
ON d1.account_id = flagged.account_id
JOIN device_use AS d2
ON d2.device_id = d1.device_id
JOIN accounts AS peer
ON peer.account_id = d2.account_id
JOIN payments AS p
ON p.from_account = peer.account_id
JOIN accounts AS ring
ON ring.account_id = p.to_account
WHERE flagged.account_id = :flagged;Six joins to reach four hops. Add a hop and you add a join; the query plan and the runtime grow with it.
-- Graph SQL (SQL/PGQ): the same question, as a pattern
SELECT ring_member
FROM GRAPH_TABLE (fraud_graph
MATCH (f:Account WHERE f.id = :flagged)
-[:USED]-> (:Device) <-[:USED]-
(:Account) -[:PAID]-> (r:Account)
COLUMNS (r.id AS ring_member)
);The pattern is the query. Standardised as SQL/PGQ in SQL:2023, alongside GQL (ISO/IEC 39075) — the first new ISO database language since SQL.
In public-sector engagements we frame this work as revenue assurance and leakage recovery. The measure that matters to a ministry is recovered revenue, not accusations — and the same graph does both.
Ready to Build Your Intelligent Enterprise?
Let's talk about your toughest infrastructure, data, or security challenge. Discovery calls are free, and we scope every engagement in writing before any work begins.