Orchestrata Ultimate › Plans › graph-consolidation-decision
Graph-consolidation decision — operational KG on orchgraph vs two-graph topology
Source: plans/graph-consolidation-decision.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-12 · 113 lines.
Prose pending.
Plan text
Graph-consolidation decision — operational KG on orchgraph vs two-graph topology
Session 227 (2026-07-12). Evidence: read-only Cypher-surface audit of the operational-KG code + live construct probes against the orchgraph cluster (
neo4j://10.92.53.160:7691)
- capacity measurements on both graphs. Question (backlog, session-225 handoff): can the operational + code-intelligence KG run on the orchgraph (Memgraph 3.11 fork, Raft HA) cluster instead of standalone Neo4j 5.26 Community at
10.92.53.11?
Recommendation
Keep the two-graph topology today. Consolidation is FEASIBLE (medium-large mechanical effort) but is blocked by five ordered prerequisites, four of which are already backlog items. Re-decide after the prerequisites land; do not start a cutover before them — migrating the current schema would carry known split-brain debt onto a new engine and compound it (ontology-before-import rule).
Evidence
What works on orchgraph today (live-probed 2026-07-12)
| Construct | Verdict |
|---|---|
datetime(), localDateTime() |
OK (tz-aware DateTime returned) |
EXISTS {} subqueries, FOREACH, SET n += map |
OK |
elementId(), id() |
OK |
Label expressions MATCH (n:A|B) |
OK |
CREATE CONSTRAINT ... IF NOT EXISTS ... REQUIRE ... IS UNIQUE |
OK (proven by semantic_graph adapter) |
Plain MERGE, DETACH DELETE, variable-length multi-type patterns |
OK |
SHOW INDEX INFO / SHOW CONSTRAINT INFO |
OK but different row shape than Neo4j SHOW INDEXES/CONSTRAINTS |
Zero occurrences in the operational write path of: CALL {} subqueries,
CALL ... IN TRANSACTIONS, ON CREATE/ON MATCH SET, write-path apoc.*.
Confirmed incompatibilities (each needs code changes before cutover)
- Schema DDL:
CREATE INDEX name IF NOT EXISTS FOR (n:L) ON (n.p)andCREATE FULLTEXT INDEX(knowledge_graph/schema.py:147-174) are Neo4j-5-only; Memgraph wantsCREATE INDEX ON :L(p)(no IF NOT EXISTS; duplicates raise). - Fulltext search:
CALL db.index.fulltext.queryNodes(knowledge_graph/search.py:48, session/kg_context.py:229) has no counterpart — the current orchgraph build shipsvector_search.*but no text-search MAGE module (probed: none loaded). apoc.path.subgraphAll(knowledge_graph/kg_context.py:246) — no APOC on Memgraph; needs a MAGE or variable-length-MATCH rewrite with parity tests.- Introspection consumers:
canonical_schema.py:516-524_live_unique_pairs(),scripts/migrate_neo4j_canonical.py:224,scripts/neo4j_test_preflight.py:88parse the Neo4j-5SHOW CONSTRAINTSrow shape (entityType/labelsOrTypes/...) — on Memgraph they silently return nothing rather than erroring. CALL db.labels()/db.relationshipTypes()(knowledge_graph/_sync_queries.py:200,209) — procedures absent (probed: FAIL).
Silent-failure hazard (fix regardless of the decision)
knowledge_graph/neo4j_client.py:117-129 ensure_schema() wraps all DDL in
try/except Exception: logger.debug(...). On Memgraph the incompatible index/fulltext DDL
would be swallowed and the KG would boot with no indexes and no fulltext, silently.
Also: ensure_schema() applies the legacy schema.py DDL while scripts/kg_schema.py /
migrate_neo4j_canonical.py apply canonical_schema.get_all_ddl() — two DDL sources of
truth (kg-schema-gaps gap #4).
Seam status
src/: onlycore/neo4j_factory.pyconstructs drivers (D12/D13 architecture-checker gate, verified); everything routes throughcore/graphrepositories orNeo4jClient, with 2 documented escape hatches (neo4j_client.py,session/kg_sync/_base.py).scripts/: 9 scripts bypass the seam with rawGraphDatabase.driver(...)(kg_schema, import_neo4j_to_memgraph, sync_architecture_to_neo4j, bootstrap_graphs, migrate_neo4j_canonical, diagnose_test_failure, neo4j_test_preflight, benchmark_pipeline, start_test_services) — each needs its own connection edit.- The seam abstracts connection construction only; it does not translate Cypher.
Tests
tests/conftest.py already indirects NEO4J_URI (+ per-worker NEO4J_URI_<SLOT>), so the
switch point is one env var — but ~237 non-semantic-graph test files touch Neo4j and every
Neo4j-behavior-dependent assertion (DDL sets, SHOW shapes, fulltext, id semantics) needs
re-validation. test_schema_completeness.py / test_canonical_schema_completeness.py
assert exact DDL statement sets and must change in lockstep.
Capacity / operations
- Operational KG: 768,139 nodes / 482,454 edges; 94% is append-only telemetry (GatewayAuditEvent 311K, Session 256K, CXPPacket 154K; recent growth ≈ 6-7K nodes/day, CXPPacket-dominated). Code-intel + structure is < 45K nodes.
- orchgraph data nodes: 32 GB RAM each, memgraph RSS 1.5 GB while already holding the 743K-node canonical import — years of headroom at current growth, BUT unbounded append-only labels in an in-memory engine need a retention/archival policy first.
- Consolidation would put operational writes on a Raft HA cluster (real failover) vs the current single Community-edition Neo4j (no clustering) — the strongest argument FOR.
- Both workloads co-mingle by label on the shared cluster (wiki + semantic + operational); isolation remains label-discipline only.
Ordered prerequisites (if consolidation is pursued)
- Fix
ensure_schema()fail-silent + unify DDL ontocanonical_schema.py(also closes kg-schema-gaps gap #4). Independent win; do it regardless. - Land the persistence funnel work already in backlog: D12 P1 ratchet + the Neo4j repo-seam swarm-refactor, and bring the 9 bypassing scripts through the factories.
- Fix kg-schema-gaps #1 (Task node), #2 (unwired provenance writers), #8 (Volk MERGE-key divergence) — never import a known-split-brain ontology onto a new engine.
- Solve fulltext: build/load a text-search MAGE module into the orchgraph fork, or
redesign
search.py+session/kg_context.pyretrieval onvector_search. - Define telemetry retention (age-out/archival for GatewayAuditEvent/CXPPacket/Session) before moving append-only growth into RAM.
Then: dual-write or import-through-ontology cutover behind the existing NEO4J_URI
indirection, per-worker test validation, and a rollback window keeping .11 warm.
Prior decisions honored
- Session-223 handoff: "Keep two graphs ... backlog #4 introduces [the seam] before any 'drop Neo4j'" — this document refines, not reverses, that ruling.
plans/neo4j-seam-design.mdnon-goal: cross-engine merge was explicitly out of scope of the seam work; this is the first concrete evaluation.