Performance¶
This guide explains how to tune the performance of your Neo4j Enterprise clusters.
Operator Performance Optimizations¶
The Neo4j Enterprise Operator includes several performance optimizations for production environments:
Reconciliation Efficiency¶
- Retry pacing: A cluster reconcile that fails is retried with exponential backoff from 5 seconds up to 30 seconds, per cluster. A shared limit of 10 retries a second (bursts of 100) only guards against a retry storm across every cluster. Scheduled passes (such as
--ready-poll-interval) and changes in Kubernetes are not paced by either - Status Update Optimization: Status updates only occur when cluster state actually changes, reducing unnecessary API server load
- ConfigMap Debouncing: A short debounce interval coalesces rapid successive configuration changes, preventing restart loops
Many large clusters¶
A Ready cluster or standalone is reconciled whenever something in Kubernetes changes (its spec, a pod, the StatefulSet) and, when nothing does, again after --ready-poll-interval (default 30s). That timed pass is how the operator notices what only Neo4j knows — a server or database turning unhealthy with no pod changing. Each pass queries Neo4j over Bolt, so one operator watching many clusters can raise the interval: at 2m, a database that goes offline shows in DatabasesHealthy within two minutes instead of thirty seconds. A cluster that is forming, upgrading, rolling or short of a server is not affected; it keeps its own cadence.
The operator keeps one Neo4j driver per cluster or standalone and reuses its connections from pass to pass, so a pass does not open new connections, perform TLS handshakes or log in again. On a quiet 3-server cluster that took the operator's logins, each a line in Neo4j's security.log, from about 17 a minute to under one. The driver is replaced when the admin password or the TLS certificates change, and closed when the deployment is deleted or has not been reconciled for 10 minutes.
Split-brain detection is the expensive part of a cluster's pass: it opens a Bolt connection to every server and compares their views of the cluster. A Ready cluster runs it in full at most every --split-brain-check-interval (default 5m), and in between relies on SHOW SERVERS through the client Service. It runs at once, on that pass, when:
- a server pod has been deleted or recreated, restarted a container, or changed readiness since the last full check — the moments a server can come back on its own and form a separate cluster;
SHOW SERVERSlists fewerEnabled,Availableservers thanspec.topology.servers;- the cluster is not
Ready(Degradedchecks on every pass); - the operator has restarted, so it has no clean check on record.
--split-brain-check-interval=0s restores a full check on every pass. With Helm, set readyPollInterval and splitBrainCheckInterval.
Clusters are reconciled four at a time (--cluster-max-concurrent-reconciles), so a cluster whose servers are slow to answer, or a pass that is busy upgrading one, does not hold up the others. A single cluster is never reconciled twice at once. Raise it if one operator runs many clusters; every worker can hold Bolt connections to one cluster's servers and makes its own requests to the Kubernetes API.
Each pass of one cluster is cut off after --cluster-reconcile-timeout (default 10m, 0s for no limit) and retried, so a pass stuck on a server that accepted a query and stopped answering gives its worker back. A normal pass takes seconds, and one against unreachable servers far less than the limit, because every Neo4j connection and query has its own timeout. With Helm, set clusterMaxConcurrentReconciles and clusterReconcileTimeout.
Resource Management¶
- Memory Validation: Automatic validation ensures Neo4j memory settings don't exceed available resources
- Resource Recommendations: Built-in recommendations for optimal CPU and memory allocation based on cluster size
- Low-overhead observability: The operator exposes a small set of Prometheus metrics (see Monitoring); it does not poll node or pod utilization itself
Resource Allocation¶
One of the most important factors for performance is resource allocation. You can configure the CPU and memory resources for your Neo4j pods using the spec.resources field in the Neo4jEnterpriseCluster resource. It is crucial to set both requests and limits for predictable performance.
Memory Validation and Recommendations¶
The operator includes intelligent memory validation that:
- Ensures Neo4j heap settings don't exceed available container memory
- Provides automatic recommendations for optimal memory allocation
- Validates memory ratios between heap, page cache, and system overhead
resources:
requests:
memory: "4Gi" # Minimum for stable operation
limits:
memory: "8Gi" # Allows 4-6GB for Neo4j heap + page cache
JVM Tuning¶
For advanced use cases, you can tune the JVM settings for your Neo4j pods using environment variables in the spec.env field. This allows you to control settings like heap size, garbage collection, and more.
env:
- name: NEO4J_server_memory_heap_initial__size
value: "4G"
- name: NEO4J_server_memory_heap_max__size
value: "4G"
- name: NEO4J_server_memory_pagecache_size
value: "2G"
Performance Monitoring¶
The operator does not track resource utilization or detect bottlenecks itself. Use the standard Kubernetes and Prometheus tooling for that, and the operator's own metrics for the operator's behaviour.
Resource utilization¶
- CPU, memory and storage: observe pod and node usage with
kubectl topor Prometheus (cAdvisor / kubelet metrics and kube-state-metrics). Compare usage withspec.resourcesand the PVC size. - Neo4j metrics: transaction rates, query counts, page-cache and JVM metrics come from Neo4j's own Prometheus endpoint, which the operator enables with
spec.monitoring.enabled(see Monitoring). - Capacity before apply:
kubectl neo4j preflight -f <manifest>checks that a Ready node has enough allocatable memory for the requested pods.
Operator behaviour¶
- Operator metrics: reconcile counts and durations, upgrade and backup outcomes, and resource-version conflicts. The full list, and which families are populated, is in Monitoring.
- Cluster health:
status.phase, theReady,ServersHealthyandDatabasesHealthyconditions, andstatus.diagnostics(liveSHOW SERVERS/SHOW DATABASES).
Best Practices¶
For Production Deployments¶
- Set appropriate resource limits: Ensure containers have sufficient CPU and memory
- Use persistent storage: Configure appropriate storage classes for your workload
- Enable monitoring: Monitor both Kubernetes and Neo4j metrics
- Plan capacity: Monitor trends and scale manually as needed
For Development Environments¶
- Use smaller resource allocations: Optimize for development machine resources
- Enable debug logging: Set log levels for troubleshooting
- Use local storage: Consider local storage for faster development cycles