GraphRAG Explained
Standard RAG works like this: embed a query, find the most similar text chunks, hand them to a language model. It is fast, general-purpose, and good at finding relevant passages.
But it has a fundamental limitation: every retrieval is independent. Each chunk is scored in isolation. There is no awareness of how entities relate to each other, no traversal of connections, no way to assemble a picture from distributed evidence.
GraphRAG solves this by replacing chunk retrieval with graph traversal.
The Core Limitation of Chunk-Based RAG
Imagine asking: "Which of our suppliers have had compliance issues and are also connected to the contract currently under review?"
A chunk-based RAG system would:
- ▸Embed the query
- ▸Find chunks semantically similar to the question
- ▸Return the top-K passages
None of those chunks individually answer the question — the answer exists in the relationships between supplier records, compliance history, and contract data. No amount of semantic similarity retrieval can surface what is inherently a graph traversal problem.
flowchart LR
subgraph CHUNKRAG["Chunk RAG — misses the connection"]
Q1[Query] --> EMB[Embed]
EMB --> NN[Find similar chunks]
NN --> C1["Chunk: supplier profile"]
NN --> C2["Chunk: compliance report"]
NN --> C3["Chunk: contract details"]
C1 -.->|no link| C2
C2 -.->|no link| C3
endflowchart LR
subgraph GRAPHRAG["GraphRAG — traverses the connection"]
Q2[Query] --> ENT["Extract entities: supplier, contract, compliance"]
ENT --> TR["Traverse graph from contract node"]
TR --> SUP["Supplier entity: linked to contract"]
SUP --> COMP["Compliance history: 2 flags"]
TR --> POL["Policy: regulated supplier — legal review required"]
SUP & COMP & POL --> CTX["Assembled context: complete picture"]
CTX --> LLM["LLM generates grounded answer"]
endHow GraphRAG Works
GraphRAG has three distinct steps that differ from standard RAG:
Step 1: Entity extraction and anchoring
Instead of embedding the raw query text, GraphRAG extracts the entities in the query and anchors them to nodes in the knowledge graph.
flowchart TD Q["Query: 'What compliance issues exist for suppliers on contract C-4421?'"] --> EE["Entity extraction"] EE --> E1["contract: C-4421"] EE --> E2["entity type: supplier"] EE --> E3["topic: compliance issues"] E1 --> KG[(Knowledge Graph: locate C-4421 node)]
Step 2: Graph traversal
Starting from the anchor node, the system traverses outbound relationships to collect connected entities and facts relevant to the query.
flowchart TD CONTRACT["Contract C-4421"] --> SUP1["Supplier: Acme Corp\n[industry: regulated]"] CONTRACT --> SUP2["Supplier: Beta Ltd\n[industry: tech]"] SUP1 --> COMP1["Compliance event: 2024-11\n[severity: high]"] SUP1 --> COMP2["Compliance event: 2025-03\n[severity: medium]"] SUP1 --> POL["Policy: regulated-vendor-review\n[status: not triggered]"] style COMP1 fill:#f43f5e,color:#fff style POL fill:#f59e0b,color:#000
The traversal is guided by the query intent — a compliance question triggers traversal through compliance-related relationship types; a financial question traverses financial relationship types.
Step 3: Context assembly and generation
The traversed subgraph is assembled into a structured context package and passed to the language model.
flowchart TD TRAV["Traversed subgraph"] --> PACK["Structured context:\n- Contract C-4421 has 2 suppliers\n- Acme Corp: regulated industry, 2 compliance flags (high+medium)\n- Policy: regulated-vendor-review not yet triggered\n- Beta Ltd: no compliance issues"] PACK --> LLM["LLM prompt: CONTEXT + QUESTION"] LLM --> ANS["'Acme Corp (regulated supplier on this contract) has 2 compliance flags — a high-severity event in Nov 2024 and medium in Mar 2025. The required regulated-vendor-review policy has not been triggered. Beta Ltd has no compliance issues.'"]
GraphRAG vs Standard RAG: When to Use Each
| Scenario | Standard RAG | GraphRAG |
|---|---|---|
| Retrieving a policy document | ✅ Good | Unnecessary overhead |
| Finding an answer in a single passage | ✅ Good | Unnecessary overhead |
| Multi-hop reasoning across entities | ❌ Misses connections | ✅ Native to graph traversal |
| Assembling a 360-view of a customer | ❌ Chunks don't link | ✅ Traverse from customer node |
| Checking business rule compliance | ❌ Rules not in text | ✅ Rules as explicit graph edges |
| Temporal reasoning across events | ❌ Chunks lack timeline | ✅ Event chains in graph |
| Questions that require joining two facts | ❌ Each chunk is separate | ✅ Traversal bridges them |
[Key Insight] Standard RAG and GraphRAG are not competing approaches — they solve different retrieval problems. The strongest production AI systems use both: standard RAG for document passage retrieval, GraphRAG for entity-centric questions that require traversing relationships.
Community Detection: Summarising at Scale
One of the most powerful GraphRAG techniques is community detection — using graph algorithms to identify clusters of tightly connected entities, then generating summaries for each community rather than for individual chunks.
flowchart TD KG[(Full Knowledge Graph)] --> COMM["Community detection algorithm\n(Leiden / Louvain)"] COMM --> C1["Community 1: Procurement cluster\n(8 suppliers, 3 policies, 12 contracts)"] COMM --> C2["Community 2: Customer cluster\n(customer segments, products, support history)"] COMM --> C3["Community 3: Compliance cluster\n(regulations, audit events, obligations)"] C1 --> SUM1["LLM: generate community summary"] C2 --> SUM2["LLM: generate community summary"] C3 --> SUM3["LLM: generate community summary"] SUM1 & SUM2 & SUM3 --> IDX["Community summary index"] Q[Query] --> IDX IDX --> RELEVANT["Select relevant community → traverse from there"]
Community summaries act as a high-level index. A broad query first identifies which community is relevant, then traverses within it — much more efficient than scanning the full graph.
The Quality Hierarchy
The quality of GraphRAG output is directly dependent on the quality of the underlying knowledge graph:
flowchart TD style L1 fill:#f43f5e,color:#fff style L2 fill:#f59e0b,color:#000 style L3 fill:#10b981,color:#fff L1["❌ Poor KG: missing entities, wrong relationships, stale data\n→ GraphRAG surfaces wrong or incomplete context"] L2["⚠ Partial KG: good coverage in one domain, gaps in others\n→ GraphRAG works for covered queries, fails silently for gaps"] L3["✅ Rich KG: complete entities, typed relationships, current data\n→ GraphRAG delivers grounded, explainable, trustworthy answers"]
This is why knowledge graph quality is not a technical detail — it is the foundational investment that determines what GraphRAG can do.
GraphRAG in Practice
A minimal GraphRAG architecture for a business domain:
flowchart LR DATA["Source systems\n(CRM, ERP, docs, events)"] --> ETL["Extraction + entity resolution"] ETL --> KG[(Knowledge Graph)] KG --> GR["GraphRAG retrieval layer"] Q[User query] --> GR GR --> LLM["Language model"] LLM --> ANS["Grounded answer with source attribution"] ANS --> AUDIT[(Audit log: which nodes traversed)]
What makes this production-ready:
- ▸Entity resolution: same entity across systems maps to one node
- ▸Relationship typing: edges carry meaning, not just connections
- ▸Freshness: graph updated as source systems change
- ▸Audit trail: every answer traceable to the graph nodes that produced it
Next in this series: Ontology and Schema Design — how to design the schema that makes a knowledge graph useful rather than just large.