Skip to main content

Neo4j

Graph database for structural memory in the Raven Model cognitive architecture.


Overview

Neo4j provides relationship-based storage for the Muninn (Memory) layer, enabling complex traversals and pattern matching that traditional databases cannot efficiently support.

PropertyValue
Imageneo4j:5-community
Containerneo4j
Ports7474 (HTTP), 7687 (Bolt)
Config~/ravenhelm/services/neo4j/
Data~/ravenhelm/data/neo4j/
URLhttps://neo4j.ravenhelm.dev

Use Cases

Neo4j is used for:

  • Structural Memory: Agent relationship graphs
  • Domain Intelligence Schema (DIS): Entity relationships and knowledge graphs
  • Neural Routing Pathways: Learned pathway weights with reinforcement/decay
  • Session Context: Conversation thread relationships

Quick Commands

# Check health
curl -s http://localhost:7474 | head -1

# Check via Bolt
docker exec neo4j cypher-shell -u neo4j -p "$NEO4J_PASSWORD" "RETURN 1"

# View logs
docker logs -f neo4j

# Restart
docker restart neo4j

# Enter Cypher shell
docker exec -it neo4j cypher-shell -u neo4j -p "$NEO4J_PASSWORD"

Cypher Quick Reference

// List all nodes by label
CALL db.labels() YIELD label RETURN label;

// Count nodes by label
MATCH (n) RETURN labels(n), count(*) ORDER BY count(*) DESC;

// List all relationships
CALL db.relationshipTypes() YIELD relationshipType RETURN relationshipType;

// Show database info
CALL dbms.components() YIELD name, versions, edition;

// Clear all data (DANGER!)
MATCH (n) DETACH DELETE n;

Configuration

docker-compose.yml

services:
neo4j:
image: neo4j:5-community
container_name: neo4j
restart: unless-stopped
environment:
- NEO4J_AUTH=neo4j/${NEO4J_PASSWORD}
- NEO4J_PLUGINS=["apoc"]
- NEO4J_server_memory_heap_initial__size=512m
- NEO4J_server_memory_heap_max__size=1G
- NEO4J_server_memory_pagecache_size=512m
- NEO4J_dbms_security_procedures_unrestricted=apoc.*
- NEO4J_dbms_security_procedures_allowlist=apoc.*
volumes:
- ../../data/neo4j/data:/data
- ../../data/neo4j/logs:/logs
- ../../data/neo4j/plugins:/plugins
networks:
- ravenhelm_net
labels:
- "traefik.enable=true"
- "traefik.http.routers.neo4j.rule=Host(\`neo4j.ravenhelm.dev\`)"
- "traefik.http.routers.neo4j.entrypoints=websecure"
- "traefik.http.routers.neo4j.tls.certresolver=cloudflare"
- "traefik.http.services.neo4j.loadbalancer.server.port=7474"
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:7474"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s

Secrets Management

Credentials stored in OpenBao at secret/neo4j:

# Get password from OpenBao
export VAULT_ADDR="http://localhost:8200"
vault kv get -field=password secret/neo4j

# Credentials also in secrets/.env
grep NEO4J ~/ravenhelm/secrets/.env
FieldPurpose
usernameAdmin user (neo4j)
passwordAdmin password
uriConnection URI

Traefik Routing

HostPortService
neo4j.ravenhelm.dev7474Browser UI

Note: Bolt protocol (7687) is internal-only via Docker network.


Monitoring

Prometheus Metrics

Neo4j metrics collected via docker-stats-exporter at :9102.

Key metrics:

  • docker_container_cpu_percent{name="neo4j"}
  • docker_container_memory_percent{name="neo4j"}
  • docker_container_memory_usage_bytes{name="neo4j"}
  • docker_container_net_rx_bytes{name="neo4j"}
  • docker_container_net_tx_bytes{name="neo4j"}

Grafana Dashboard

Dashboard: Neo4j (UID: neo4j)

Panels:

  • Status (up/down)
  • CPU Usage Gauge
  • Memory Usage Gauge
  • CPU/Memory Time Series
  • Network I/O Rate

Alerts

Prometheus alert rules in /etc/prometheus/rules/neo4j-alerts.yml:

AlertConditionSeverity
Neo4jDownContainer not runningcritical
Neo4jHighMemoryMemory > 80% for 5mwarning
Neo4jHighCPUCPU > 80% for 10mwarning

Health Check

# Container status
docker ps | grep neo4j

# HTTP endpoint
curl -s http://localhost:7474

# Bolt connection (requires password)
docker exec neo4j cypher-shell -u neo4j -p "$NEO4J_PASSWORD" "RETURN 'healthy' AS status"

# Database size
docker exec neo4j du -sh /data/databases

Backup & Restore

Create Backup

# Stop writes during backup (optional for consistency)
docker exec neo4j neo4j-admin database dump neo4j --to-path=/data/backups/

# Copy backup locally
docker cp neo4j:/data/backups/neo4j.dump ~/ravenhelm/backups/neo4j_$(date +%Y%m%d_%H%M%S).dump

Restore

# Copy backup into container
docker cp backup.dump neo4j:/data/backups/

# Stop database and restore
docker exec neo4j neo4j-admin database load neo4j --from-path=/data/backups/ --overwrite-destination=true

# Restart
docker restart neo4j

Troubleshooting

Issue: Container Restart Loop

Symptoms: Neo4j keeps restarting

Diagnosis:

docker logs neo4j | tail -50
ls -la ~/ravenhelm/data/neo4j/

Solutions:

  1. Ensure data directories exist with correct permissions
  2. Check memory settings aren't exceeding available RAM
  3. Verify password format in NEO4J_AUTH

Issue: Cannot Connect

Symptoms: Services can't reach Neo4j

Diagnosis:

docker ps | grep neo4j
curl http://localhost:7474
docker network inspect ravenhelm_net | grep neo4j

Solutions:

  1. Verify container is on ravenhelm_net
  2. Check Bolt port 7687 is exposed internally
  3. Verify credentials match OpenBao secrets

Issue: Out of Memory

Symptoms: OOM kills, slow queries

Diagnosis:

docker stats neo4j --no-stream

Solutions:

  1. Reduce heap size in environment vars
  2. Reduce page cache size
  3. Archive old data

Integration

Python Driver

from neo4j import GraphDatabase

uri = "bolt://neo4j:7687"
driver = GraphDatabase.driver(uri, auth=("neo4j", password))

with driver.session() as session:
result = session.run("MATCH (n) RETURN count(n) as count")
print(result.single()["count"])

LangGraph Integration

Neo4j is used with LangGraph for agent memory:

# Store agent interaction as relationship
session.run("""
MERGE (a:Agent {id: $agent_id})
MERGE (u:User {id: $user_id})
CREATE (a)-[:INTERACTED {timestamp: datetime(), session: $session_id}]->(u)
""", agent_id=agent_id, user_id=user_id, session_id=session_id)