🆕 New to KubeDB? Start with the quickstart guide before continuing here.

Neo4j Vertical Scaling with KubeDB

Vertical scaling adjusts the CPU and memory requests and limits on running Neo4j pods without recreating the database or losing data. KubeDB handles the rollout automatically through Neo4jOpsRequest.

This guide walks you through:

  • Deploying a Neo4j cluster
  • Checking current pod resource allocation
  • Applying a vertical scale-up
  • Verifying the new resources are live

How It Works

KubeDB uses Neo4jOpsRequest with type: VerticalScaling to update pod resources. Under the hood it:

  1. Patches the StatefulSet container spec with the new CPU/memory values
  2. Performs a rolling restart of Neo4j pods one at a time
  3. Marks the operation Successful once all pods are running with the new resources

Prerequisites

RequirementDetails
KubeDB installedProvisioner and Ops-manager operators running
kubectl configuredWith permissions to create namespaces and resources

See also: Neo4j · Neo4jOpsRequest · Vertical Scaling Overview


Step 1 — Set Up the Namespace

$ kubectl create ns demo

Step 2 — Deploy Neo4j

Save this as neo4j.yaml:

apiVersion: kubedb.com/v1alpha2
kind: Neo4j
metadata:
  name: neo4j-test
  namespace: demo
spec:
  version: "2025.12.1"
  replicas: 3
  storage:
    resources:
      requests:
        storage: 2Gi
    storageClassName: standard
    accessModes:
      - ReadWriteOnce
  podTemplate:
    spec:
      resources:
        requests:
          cpu: "250m"
          memory: "1Gi"
        limits:
          cpu: "500m"
          memory: "1Gi"
  deletionPolicy: WipeOut

Apply it and wait for the cluster to become ready:

$ kubectl apply -f neo4j.yaml

$ kubectl get neo4j -n demo neo4j-test -w

Wait until STATUS shows Ready before proceeding.

NAME         VERSION     STATUS   AGE
neo4j-test   2025.12.1   Ready    3m

Step 3 — Check Current Pod Resources

Before scaling, record the existing CPU and memory values so you can confirm the change later.

$ kubectl get pod -n demo neo4j-test-0 \
  -o jsonpath='{.spec.containers[0].resources}' | jq .

Expected output:

{
  "limits":   { "cpu": "500m",  "memory": "1Gi" },
  "requests": { "cpu": "250m",  "memory": "1Gi" }
}

Step 4 — Apply the Vertical Scaling OpsRequest

The Neo4jOpsRequest below raises the CPU limit to 1500m and memory to 4Gi.

Save this as neo4j-vertical-scale.yaml:

apiVersion: ops.kubedb.com/v1alpha1
kind: Neo4jOpsRequest
metadata:
  name: neo4j-vertical-scale
  namespace: demo
spec:
  type: VerticalScaling
  databaseRef:
    name: neo4j-test
  verticalScaling:
    server:
      resources:
        requests:
          cpu: "700m"
          memory: "4Gi"
        limits:
          cpu: "1500m"
          memory: "4Gi"

Apply it and wait for completion:

$ kubectl apply -f neo4j-vertical-scale.yaml

$ kubectl wait --for=jsonpath='{.status.phase}'=Successful \
  neo4jopsrequest/neo4j-vertical-scale \
  -n demo --timeout=600s

Expected output:

neo4jopsrequest.ops.kubedb.com/neo4j-vertical-scale condition met

What Happens During This Step

Once you apply the OpsRequest, KubeDB Ops-manager picks it up and begins the scaling process:

  1. The OpsRequest moves to Progressing phase
  2. KubeDB patches the StatefulSet with the new resource values
  3. Pods are restarted one at a time — each must reach Running before the next restarts
  4. Once all pods are up with the new resources, the OpsRequest moves to Successful

You can watch the live status with:

$ kubectl get neo4jopsrequest -n demo neo4j-vertical-scale -w

Step 5 — Verify the New Resources

$ kubectl get neo4jopsrequest -n demo neo4j-vertical-scale

$ kubectl get pod -n demo neo4j-test-0 \
  -o jsonpath='{.spec.containers[0].resources}' | jq .

Expected output:

NAME                   TYPE              STATUS       AGE
neo4j-vertical-scale   VerticalScaling   Successful   101s

{
  "limits":   { "cpu": "1500m", "memory": "4Gi" },
  "requests": { "cpu": "700m",  "memory": "4Gi" }
}

✅ The values now match spec.verticalScaling.server.resources — the scaling is complete.


Understanding the OpsRequest Fields

FieldDescription
spec.typeVerticalScaling — identifies this as a resource update operation
spec.databaseRef.nameName of the target Neo4j resource
spec.verticalScaling.server.resources.requestsMinimum CPU/memory guaranteed to the pod
spec.verticalScaling.server.resources.limitsMaximum CPU/memory the pod is allowed to use

Tip: Always set requests equal to limits for Neo4j in production. This gives the pod a Guaranteed QoS class, preventing it from being evicted under memory pressure.


Troubleshooting

If this OpsRequest does not finish, first inspect the affected pod and then check the kubedb-ops-manager operator logs for the exact error. For a shared checklist, see the Neo4j Ops Request Overview.

OpsRequest stays in Progressing and never completes

Check the pod that is being restarted and look for scheduling or resource issues:

$ kubectl get pods -n demo -l app.kubernetes.io/instance=neo4j-test
$ kubectl describe pod -n demo neo4j-test-0
$ kubectl describe node <node-name> | grep -A 10 "Allocated resources"

OpsRequest moves to Failed

Read the failure condition and then inspect the kubedb-ops-manager logs:

kubectl get neo4jopsrequest -n demo neo4j-vertical-scale -o jsonpath='{.status.conditions}' | jq .
kubectl logs -n <kubedb-namespace> -l app.kubernetes.io/name=kubedb-ops-manager --tail=50

Pod restarts repeatedly after scaling (CrashLoopBackOff)

If Neo4j does not start with the new memory values, inspect the previous pod logs:

kubectl logs -n demo neo4j-test-0 --previous

jq not installed

Use jsonpath directly:

kubectl get neo4jopsrequest -n demo neo4j-vertical-scale -o jsonpath='{.status.conditions}'

Cleanup

kubectl delete neo4jopsrequest -n demo neo4j-vertical-scale
kubectl delete neo4j -n demo neo4j-test
kubectl delete ns demo

Next Steps