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.
| Property | Value |
|---|---|
| Image | neo4j:5-community |
| Container | neo4j |
| Ports | 7474 (HTTP), 7687 (Bolt) |
| Config | ~/ravenhelm/services/neo4j/ |
| Data | ~/ravenhelm/data/neo4j/ |
| URL | https://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
| Field | Purpose |
|---|---|
username | Admin user (neo4j) |
password | Admin password |
uri | Connection URI |
Traefik Routing
| Host | Port | Service |
|---|---|---|
| neo4j.ravenhelm.dev | 7474 | Browser 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:
| Alert | Condition | Severity |
|---|---|---|
| Neo4jDown | Container not running | critical |
| Neo4jHighMemory | Memory > 80% for 5m | warning |
| Neo4jHighCPU | CPU > 80% for 10m | warning |
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:
- Ensure data directories exist with correct permissions
- Check memory settings aren't exceeding available RAM
- 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:
- Verify container is on ravenhelm_net
- Check Bolt port 7687 is exposed internally
- Verify credentials match OpenBao secrets
Issue: Out of Memory
Symptoms: OOM kills, slow queries
Diagnosis:
docker stats neo4j --no-stream
Solutions:
- Reduce heap size in environment vars
- Reduce page cache size
- 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)
Related
- Infrastructure Overview
- PostgreSQL - Primary relational database
- Redis - Caching layer
- Observability - Monitoring stack