Skip to content

[Bug]: Neo4j performance warnings: Cartesian product in Cypher queries during load testing #906

Description

@sscargal

Describe the bug

During load testing, see #837, the docker logs from the memmachine-app container show repeated Neo4j performance notifications indicating potential inefficiency. The logs report that Cypher queries trigger cartesian product warnings due to disconnected patterns in the MATCH clause, which may cause excessive data generation and slowdowns during query processing.

Steps to reproduce

  1. Run MemMachine's load test suite or simulate bulk operations involving edge creation in Neo4j.
  2. Monitor the memmachine-app container logs.
  3. Observe [INFO] neo4j.notifications lines with messages about cartesian products, example:
    Received notification from DBMS server: <GqlStatusObject gql_status='03N90', status_description='info: cartesian product. The disconnected patterns ... build a cartesian product. A cartesian product may produce a large amount of data and slow down query processing.'> for query: 'UNWIND $edges AS edge\nMATCH    (source:SANITIZED_Derivative... {uid: edge.source_uid}),    (target:SANITIZED_Episode... {uid: edge.target_uid})\nCREATE (source) -[r:SANITIZED_DERIVED_FROM...]-> (target)\nSET r += edge.properties'
    

Expected behavior

Cypher queries should avoid producing cartesian products unless intended. Queries should match only related node pairs, and logs should not contain unexpected performance warnings. Overall load test performance should not be negatively impacted by inefficient query planning.

Environment

  • OS: Linux
  • MemMachine Version: (latest under load testing, specify exact version if available)
  • Development language version: Python 3.x
  • Database: Neo4j (version as configured for docker load tests)

Additional context

Docker logs from the memmachine-app container repeatedly show Neo4j cartesian product performance notifications like:

2026-01-06 22:47:07,920 [INFO] neo4j.notifications - Received notification from DBMS server: <GqlStatusObject gql_status='03N90', status_description='info: cartesian product. The disconnected patterns `(source:SANITIZED_Derivative_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_cc139ee1 {uid: edge.source_uid}), (target:SANITIZED_Episode_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_cc139ee1 {uid: edge.target_uid})` build a cartesian product. A cartesian product may produce a large amount of data and slow down query processing.', ...> for query: 'UNWIND $edges AS edge\nMATCH    (source:SANITIZED_Derivative_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_cc139ee1 {uid: edge.source_uid}),    (target:SANITIZED_Episode_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_cc139ee1 {uid: edge.target_uid})\nCREATE (source)    -[r:SANITIZED_DERIVED_u5f_FROM_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_cc139ee1 {uid: edge.uid}]->    (target)\nSET r += edge.properties'
2026-01-06 22:47:07,921 [INFO] neo4j.notifications - Received notification from DBMS server: <GqlStatusObject gql_status='03N90', status_description='info: cartesian product. The disconnected patterns `(source:SANITIZED_Derivative_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_7e3661c7 {uid: edge.source_uid}), (target:SANITIZED_Episode_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_7e3661c7 {uid: edge.target_uid})` build a cartesian product. A cartesian product may produce a large amount of data and slow down query processing.', ...> for query: 'UNWIND $edges AS edge\nMATCH    (source:SANITIZED_Derivative_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_7e3661c7 {uid: edge.source_uid}),    (target:SANITIZED_Episode_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_7e3661c7 {uid: edge.target_uid})\nCREATE (source)    -[r:SANITIZED_DERIVED_u5f_FROM_u5f_benchmark_u5f_org_u2f_benchmark_u5f_project_u5f_7e3661c7 {uid: edge.uid}]->    (target)\nSET r += edge.properties'

These appear after running bulk/batch ingestion and do not halt operation, but suggest query optimization opportunities.

Activity

  1. added theissue type on Jan 7, 2026
  2. self-assigned this
    on Jan 7, 2026
  3. sscargal commented on Jan 7, 2026

    @sscargal
    ContributorAuthor

    Based on my initial analysis, it seems highly likely that the performance warnings (Cartesian product alerts and slowdowns) observed during bulk/batch ingestion in Neo4j are connected to the delayed creation of an index on the uid property. Here’s my hypothesis with known Neo4j and graph database behavior:

    Key points:

    • The codebase uses a threshold (default 10,000 nodes) before it creates an index on uid.
    • Until that threshold is reached, Cypher queries matching nodes (e.g., MATCH (n {uid: ...})) must perform a full scan of all nodes with the label, i.e., an $O(N)$ operation.
    • When using bulk operations with many MATCH clauses and disconnected patterns, this leads to full scans for each source/target lookup prior to the CREATE, easily causing cartesian products, excessive data generation, and slow query planning.
    • As the node count grows, each new write gets slower due to the lack of index support.

    Effects:

    • The UNWIND + MATCH (source ...), (target ..) pattern produces a cartesian product warning if the two patterns are not connected by a variable in the MATCH. This is worsened if there are no indexes to efficiently look up nodes by uid.
    • Before hitting the node threshold, every write is highly inefficient; after that, index creation should rapidly improve per-write speed and reduce cartesian product risk.

    Next steps for investigation:

    1. Locate the threshold and index creation logic: Find where in the codebase the logic checks node count and creates an index on uid once >10,000 nodes exist.
    2. Review Cypher query construction: See if the pattern could be revised to connect the source/target lookups and avoid accidental cartesian products, e.g., by using a single MATCH with both nodes linked by an edge variable.
    3. Potential improvement: Consider lowering the threshold for index creation or checking if the deployment can support up-front index creation to reduce early insert cost and noisy warnings drastically.

    Suggested next steps:

    • Find the exact file and line where this threshold is enforced and how index creation is triggered
    • Research suggestions for safer bulk Cypher query patterns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions