Graph DB best practices — Neo4j & Memgraph
Source: 106-agent deep-research workflow (session 242, 2026-07-21), findings
adversarially verified (3-vote refutation). Full report with citations:
reports/research-graph-db-best-practices.md in the orchestrata-ultimate repo.
Neo4j (operational KG, 10.53.1.11, ~800k nodes)
- Every property predicate needs a label to use an index. Property
indexes are label-scoped;
MATCH (n) WHERE n.prop = $xfull-scans the node store. Measured here: ~260ms per sweep on 803,688 nodes vs ~6ms label-bounded. Two built-in token-lookup indexes serve bare label scans. - RANGE indexes support
STARTS WITH(used for the Sessionsession_idprefix seeks); TEXT indexes are the right tool forCONTAINS/ENDS WITH— candidates here:Session.session_id, code-intelligencequalnamelookups. - PROFILE, not EXPLAIN, for real db-hits; plan cache makes the first parameterized run pay compile cost — keep queries parameterized so the cache hits.
- Without GDS Enterprise: shortest-path (
shortestPath()/apoc.path) is native; PageRank/community-detection/betweenness need GDS Community (free, ALL algorithms, 4-core cap, in-memory projections) — worth installing for the code-intelligence graph. - Page cache sizing: keep the store fully memory-resident
(store ≈ few GB here; check
server.memory.pagecache.size).
Memgraph (shared semantic/RAG graph, orchgraph HA)
storage.access_timeout_secdefault 1s is too tight under concurrent access — a reader polling during a bulk write aborts the writer. APPLIED: 60s at all 3 layers (runtimeSET DATABASE SETTINGon both data instances, persistent systemd units via incus file push, rebuild templateinfra/rehearsal/provision_node.sh).- Index creation scans the entire vertex store even for an empty label (2,514ms measured). Never create per-test/per-batch indexes; create once, isolate by data.
- IN_MEMORY_ANALYTICAL is bulk-load-only here — it is incompatible with replication/HA, so the Raft cluster must stay IN_MEMORY_TRANSACTIONAL; analytical mode is only for offline single-node rebuilds.
- HNSW vector search: deleted vertices can surface as "Returning a
deleted object" for a settle window (>10s, survives sessions) — treat
deletes under a live vector index as unsafe mid-workload; prefer
tombstoning or end-of-run cleanup. Tune
m/ef_constructionat index creation,ef(search) per query. - MAGE algorithms are fully available in community (PageRank, Louvain, betweenness, etc. as query modules) — the semantic graph can run GraphRAG-adjacent analytics without any license.
Actionable items for this stack
| # | Item | Status |
|---|---|---|
| 1 | Memgraph access timeout 1s → 60s (3 layers) | DEPLOYED |
| 2 | Label-bounded sweeps (tests) + label-scoped production search (_contains_search, QueryEngine.search) |
DONE (d1c6733a, 9c5cc9d3, ffbb1a91) |
| 3 | TEXT indexes for CONTAINS lookups (Class/Function/Predicate name) | DEPLOYED (all 4 DBs, ffbb1a91) |
| 4 | GDS Community 2.13.2 on neo4j-db (PageRank on CALLS: proj 1.43s, PR 0.33s) | DEPLOYED (698b0845) |
| 5 | Page-cache/heap sizing (256M/512M → 2g/1g primary, 1g/1g workers) | DEPLOYED (rolling restart verified) |
| 6 | Orchgraph fork: concurrent/online index build patch check | backlogged |
Related: Running the test suite · Suite speedup story · Graph databases (concepts)