Why We Compared LightRAG and Microsoft GraphRAG
We brought LightRAG and Microsoft GraphRAG into our review because graph retrieval creates a budgeting problem before it creates a retrieval advantage.
A vector index is relatively easy to cost. We chunk documents, embed the chunks, store the vectors, and pay for one generation request per query. For LightRAG, we budget for index-time LLM entity and relationship extraction and profiling, alongside deduplication and embeddings. Full Microsoft GraphRAG also builds hierarchical communities and generates community reports before serving queries. LazyGraphRAG follows a different pattern: it builds its concept graph without LLM calls and defers LLM work until query time.
The architectural distinction matters.
LightRAG builds a graph of entities and relationships alongside vector indexes. Its local retrieval mode targets specific entities and their connections. Its global mode retrieves broader concepts and themes. It avoids Microsoft GraphRAG's full hierarchy of precomputed community reports, which reduces indexing work but does not make indexing free. Entity and relationship extraction still consume prompt and completion tokens.
Microsoft GraphRAG's full indexing pipeline is heavier. It extracts entities and relationships, consolidates descriptions, detects hierarchical communities, and generates summaries used by global search. Local search combines graph records with source text. Global search performs map-reduce-style reasoning over community reports.
LazyGraphRAG is a separate cost model, not a cheaper name for the same pipeline. It uses noun-phrase extraction and graph statistics during indexing, skips LLM-generated community summaries, and defers LLM work until query time. That can radically lower initial indexing cost while making query cost dependent on relevance-test budgets and the number of subqueries.
Our central question was therefore not, “Which graph system is fastest?” It was:
Does the quality gain from graph retrieval repay the indexing bill and additional operational complexity at the expected query volume?
For a repeatable comparison, we would freeze a 20–50-document corpus, separate local and global query classes, and use a common chat model and embedding model. We would record wall-clock indexing time, LLM request count, input and output tokens, estimated API spend, cold and warm query latency, and evidence-grounded answer quality.
We do not have a complete, defensible four-way numeric ledger. We could inspect the historical comparison's setup, but not its numerical results. Our only fully reproduced experiment concerned requirement parsing for a document-ingestion dependency. We will not convert missing measurements into plausible-looking benchmark data.
That limitation is itself useful. We identified several comparability risks: version differences, a changed chat-model tier, and a single-file literary corpus. We also could not establish whether prompts, chunking, and query text stayed identical between the historical rounds. Those limits prevent us from transferring their costs directly to a production budget.
Hands-On Walkthrough: Setup, Execution & Output
We verified that the current packaged LightRAG distribution is named lightrag-hku, not lightrag. For server installation, the API extra is the relevant path:
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "lightrag-hku[api]"
cp env.example .env
# Configure the LLM, embedding provider, dimensions, and authentication.
lightrag-server
For library use, install the base package:
python -m pip install lightrag-hku
For Microsoft GraphRAG, we initialized a project root, placed source documents under the configured input directory, and used its indexing CLI:
python -m venv .venv-graphrag
source .venv-graphrag/bin/activate
python -m pip install graphrag
graphrag init --root ./graphrag-workspace
# Edit settings.yaml and place text files in the configured input directory.
graphrag index --root ./graphrag-workspace
graphrag query \
--root ./graphrag-workspace \
--method local \
--query "Which components depend on the Atlas gateway?"
graphrag query \
--root ./graphrag-workspace \
--method global \
--query "What recurring operational risks appear across the corpus?"
For reproducible cost accounting, we would count requests at the HTTP client boundary rather than infer them from framework log lines. We would track retries separately and use provider-returned usage fields to determine token spend. We would tag chat and embedding requests by phase and measure wall time with a monotonic clock.
The ledger needs at least these fields:
{
"engine": "lightrag",
"version": "pinned-version-or-commit",
"phase": "index",
"operation": "entity_relation_extraction",
"request_count": 1,
"input_tokens": 2941,
"output_tokens": 612,
"retry_count": 0,
"elapsed_ms": 1842,
"model": "configured-chat-model"
}
This JSON object illustrates a proposed ledger format; its values are placeholders, not benchmark results.
We also isolated the ingestion failure associated with the historical textract path. The following check is runnable and reproduces the requirement-parser problem without downloading or installing the affected document parser:
from packaging.requirements import Requirement, InvalidRequirement
from packaging.version import Version
requirements = [
"extract-msg<=0.29.*",
"extract-msg<=0.29",
"extract-msg<0.30",
"extract-msg==0.29.*",
]
for value in requirements:
try:
parsed = Requirement(value)
print(f"ACCEPTED {value}: {parsed.specifier}")
except InvalidRequirement as exc:
print(f"REJECTED {value}: {type(exc).__name__}")
versions = ["0.28.9", "0.29", "0.29.1", "0.30"]
for specifier in ["<=0.29", "<0.30", "==0.29.*"]:
requirement = Requirement(f"extract-msg{specifier}")
accepted = {
version: Version(version) in requirement.specifier
for version in versions
}
print(specifier, accepted)
With Python 3.12.14 and packaging==24.2, our output was:
REJECTED extract-msg<=0.29.*: InvalidRequirement
ACCEPTED extract-msg<=0.29: <=0.29
ACCEPTED extract-msg<0.30: <0.30
ACCEPTED extract-msg==0.29.*: ==0.29.*
<=0.29 {'0.28.9': True, '0.29': True, '0.29.1': False, '0.30': False}
<0.30 {'0.28.9': True, '0.29': True, '0.29.1': True, '0.30': False}
==0.29.* {'0.28.9': False, '0.29': True, '0.29.1': True, '0.30': False}
This check does not prove that a patched textract installation can parse PDF or Office files. It proves only that the malformed wildcard constraint is rejected and that casually deleting the wildcard changes dependency semantics.
In a repeatable benchmark, we would treat local and global modes separately rather than combine retrieval and answer generation into one opaque timer. We would record these phases for each query:
- Query preprocessing or keyword extraction.
- Query embedding.
- Graph and vector retrieval.
- Context construction.
- Answer generation.
- Total end-to-end latency.
That separation matters because a “fast retrieval” result can still produce a slow answer when the retrieved graph context is large.
Teams building a repeatable evaluation can adapt this ledger to their own stack or use our broader tools collection as a starting point.
Version, Configuration, and Operational Limitations
The first problem was version comparability.
In our version review, we kept the paper-era architecture separate from the broader 2026 package, which includes multiple chunking strategies, role-specific model configuration, reranking, multimodal parsing, several storage backends, and deletion workflows. We identified two distinct historical setups: an unpinned LightRAG source checkout paired with Microsoft GraphRAG 0.5.0, and a LightRAG 1.2.5 evaluation requiring internal patches to return retrieved context.
Those are not interchangeable systems. We would not compare a current LightRAG build against GraphRAG 0.5.0 and call the result a 2026 product benchmark.
The second configuration check is embedding compatibility. We would pin the embedding model, output dimensions, vector-store schema, and query-time embedding configuration together. We verified that the historical comparison selected text-embedding-3-small, but we did not establish the dimensions configured for either engine or test dimension-mismatch behavior. We would validate any model or dimension change as an index migration before deployment.
Third, graph extraction cost is controlled more by chunks than by files. A 20-file corpus can become hundreds of extraction prompts if files are long, chunk size is small, overlap is high, or extraction retries are enabled. “Cost per document” is therefore the wrong planning unit.
Our useful planning approximation is:
index cost =
extraction input tokens
+ extraction output tokens
+ entity/relation consolidation tokens
+ community-summary tokens
+ embedding tokens
+ retry overhead
LightRAG removes some of the community-report work associated with full GraphRAG, but it still pays for graph extraction and profile generation. Full GraphRAG adds community summarization, which can dominate a small corpus because fixed prompt scaffolding is repeated across many operations.
Fourth, document ingestion is separate from retrieval architecture. The malformed extract-msg<=0.29.* constraint was an immediate blocker on the older textract path. We did not accept “remove the asterisk” as a safe fix. As our parser check showed, <=0.29 rejects 0.29.1, while <0.30 admits it. The correct repair depends on the dependency author's intended range and requires parser regression tests.
For production, we prefer explicit ingestion adapters for plain text, Markdown, PDF, and Office files over a large transitive parser bundle. We persist normalized text and document hashes before either graph engine sees the content.
Fifth, incremental insertion is not the same as editing. LightRAG can process a new document without rebuilding the whole corpus. For an existing document edit, however, we need deterministic document IDs, deletion or invalidation of old chunks, and regeneration of affected graph records. Cache reuse can reduce work, but it does not guarantee zero extraction calls.
GraphRAG 0.5.0 introduced incremental update support, yet its behavior still needs testing against the exact current release and storage configuration. We did not retain a valid measurement for the number of calls caused by a one-document edit, so we will not assign a percentage saving.
Finally, LightRAG's default local KV, vector, and graph stores are suitable for evaluation, not a production capacity test. File-backed persistence surviving a restart does not make those stores equivalent to PostgreSQL, Neo4j, OpenSearch, or another networked backend. We must benchmark production I/O, locking, backup, and concurrent-query behavior on the backend we intend to operate.
Scale, Latency & Cost vs. Alternatives
Here is the comparison we can defend. “Not established” means the test artifacts did not support a trustworthy number—not that the operation has zero cost.
| Option | Index-time work | Query-time pattern | Measured wall time and latency | Measured request and token spend | Best fit |
|---|---|---|---|---|---|
| LightRAG local | Entity and relation extraction, profiling, deduplication, embeddings | Entity-focused graph and vector retrieval, then generation | Not established | Not established in a complete retained run | Questions about named entities and connected facts |
| LightRAG global | Same shared LightRAG index | Theme-level retrieval over graph-derived keys, then generation | Not established in a complete retained run | Not established in a complete retained run | Broad questions where full GraphRAG reports are too expensive |
| GraphRAG local | Extraction, consolidation, graph construction, embeddings, and supporting summaries | Entity and source-text context, then generation | Not established in a complete retained run | Not established in a complete retained run | Rich entity-centric investigation |
| GraphRAG global | Full graph plus hierarchical community reports | Map-reduce reasoning over community reports | Not established in a complete retained run | Not established in a complete retained run | Corpus-wide synthesis where breadth is worth the cost |
| LazyGraphRAG | NLP concept extraction and graph statistics, without index-time LLM summarization | Deferred relevance testing, claim extraction, and answer reduction | We did not verify it as a comparable open-source CLI mode | We did not reproduce Microsoft's numeric claims | Cost-sensitive global retrieval with higher query-time variability |
| Vector-only RAG | Chunk embeddings | Similarity search and one answer-generation path | Must be measured on the same corpus and model | Usually the lowest indexing bill | Local questions and small corpora |
In our cost-model review, we kept LazyGraphRAG's indexing claim separate from query cost: indexing matched vector RAG and cost 0.1% of full GraphRAG indexing in the research configuration. We also examined lower-query-cost configurations, but did not reproduce those results. We keep both claims scoped to 5,590 news articles, 100 synthetic queries, specific relevance-test budgets, and LLM-based pairwise quality judgments.
That scale is fundamentally different from the proposed 20–50-document benchmark.
For a buyer, the correct break-even calculation is:
break-even queries =
(graph index cost - vector index cost)
/
(vector cost per query - graph cost per query)
If graph queries cost more than vector queries, there is no cost-only break-even. The graph system must produce enough quality improvement to reduce human review, failed answers, escalations, or downstream agent retries.
We also calculate edit break-even separately:
monthly total =
initial index cost
+ monthly update cost
+ query count × query cost
+ storage and operations cost
There is no universal minimum corpus size at which graph indexing begins to pay. Document count is a weak proxy. Relationship density, cross-document dependencies, query mix, update frequency, and error cost matter more.
For fewer than roughly a few dozen documents, our default architecture decision remains vector or hybrid retrieval unless an evaluation demonstrates a material gain on global, multi-document questions. That is a deployment heuristic, not a measured universal threshold. On a small corpus, long-context generation may also be cheaper and simpler than maintaining a graph.
In our architecture review, we identified dual-level retrieval and incremental insertion as relevant capabilities, but established no transferable break-even corpus size. When we inspected the older LightRAGTest comparison harness, we could verify CLI and model setup, not numerical results. Its single-file literary corpus, older versions, laptop hardware, and changed chat-model tier prevent us from treating it as a current production budget.
Our Final Verdict: When to Deploy, When to Skip
LightRAG is the more practical starting point when we need graph-assisted retrieval without committing immediately to full community-report generation. Its dual-level design maps cleanly to entity-specific and thematic questions, and its incremental architecture is better aligned with frequently changing knowledge bases.
Microsoft GraphRAG remains the stronger conceptual fit when global corpus synthesis is the core product feature and we can afford a substantial preprocessing pipeline. Its global search is not merely vector search with graph labels; the community-report hierarchy is the feature and the expense.
LazyGraphRAG is strategically interesting because it moves that expense from ingestion to query time. We would not put its headline ratios into a financial model until we can run the exact implementation, model mix, relevance-test budget, and corpus ourselves. The Microsoft research description is evidence for the design, not a quote for our cloud bill.
Deploy LightRAG if:
- Entity relationships materially affect answer quality.
- The corpus changes often enough that full rebuilds are unacceptable.
- We can pin package versions, prompts, chunking, and embedding dimensions.
- We are prepared to move beyond the default local stores.
- We can meter extraction and query calls at the provider boundary.
- Local and global queries are evaluated separately.
Deploy full GraphRAG if:
- Corpus-wide synthesis is a primary user workflow.
- Community reports demonstrably improve answer completeness.
- The index changes slowly relative to query volume.
- We can absorb and monitor the up-front summarization bill.
- We need the richer local, global, and DRIFT search portfolio.
Hold off or avoid both if:
- Most questions are direct “who,” “what,” “when,” or “where” lookups.
- The corpus contains only a few dozen short documents.
- Source documents change continuously.
- We cannot build a citation-based quality set.
- A vector baseline has not been measured first.
- The business case depends on benchmark numbers from different versions or corpora.
Our blunt conclusion is that LightRAG is easier to justify operationally than full Microsoft GraphRAG, but neither earns deployment merely by producing an attractive graph visualization. The graph has to improve the questions customers actually ask.
Before approving either system, we would run a vector baseline, freeze a representative corpus, instrument every model call, edit one existing document, and calculate break-even using our own traffic forecast. If that experiment is difficult to design internally, contact our architecture team or review our implementation work under AI infrastructure services. The expensive mistake is not choosing the “wrong” graph framework. It is committing to graph indexing without knowing which query failures it is supposed to fix.
Top comments (0)