Scale a Neo4j deployment

Neo4j supports both vertical and horizontal scaling.

Vertical scaling

To increase or decrease the resources (CPU, memory) available to a Neo4j instance, change the neo4j.resources object in the values.yaml file to set the desired resource usage, and then perform a helm upgrade.

If you change the memory allocated to the Neo4j container, you should also change the Neo4j’s memory configuration (server.memory.heap.initial_size and server.memory.pagecache.size in particular). See Configure Resource Allocation for more details.

For example, if your running Neo4j instance has the following allocated resources:

# values.yaml
neo4j:
  resources:
    cpu: "1"
    memory: "3Gi"

# Neo4j Configuration (yaml format)
config:
  server.memory.heap.initial_size: "2G"
  server.memory.heap.max_size: "2G"
  server.memory.pagecache.size: "500m"

And, you want to increase them to 2 CPUs and 4 GB of memory (allocating additional memory to the pagecache).

  1. Modify the values.yaml file to set the desired resource usage:

    # values.yaml
    neo4j:
      resources:
        cpu: "2"
        memory: "4Gi"
    
    # Neo4j Configuration (yaml format)
    config:
      server.memory.heap.initial_size: "2G"
      server.memory.heap.max_size: "2G"
      server.memory.pagecache.size: "1G"
  2. Run helm upgrade with the modified deployment values.yaml file and the Neo4j Helm chart to apply the changes. For example:

    helm upgrade <release-name> neo4j/neo4j -f values.yaml

Horizontal scaling

You can add a new server to the Neo4j cluster to scale out write or read workloads.

The following examples assume that you have a running Neo4j cluster with 3 servers and your Kubernetes cluster has a node available for the new server, server4.

Install server4 using one of the following options:

Add a new server and enable it manually

  1. Install server4 using the same value for neo4j.name as your existing cluster:

    helm install server4 neo4j --set neo4j.edition=enterprise --set neo4j.acceptLicenseAgreement=yes --set volumes.data.mode=defaultStorageClass --set neo4j.password="password" --set neo4j.minimumClusterSize=3 --set neo4j.name=my-cluster

    Alternatively, you can use a values.yaml file to set the values for the new server and the neo4j/neo4j Helm chart to install the new server. For more information, see Create Helm deployment values files and Install Neo4j cluster servers.

    When the new server joins the cluster, it will initially be in the Free state.

  2. Enable server4 to be able to host databases by using cypher-shell (or Neo4j Browser) to connect to one of the existing servers:

    1. Access the cypher-shell on server1:

      kubectl exec -ti server1-0 -- cypher-shell -u neo4j -p password -d neo4j
    2. When the cypher-shell prompt is ready, verify that server4 is in the Free state, and take a note of its name:

      SHOW SERVERS;
      +---------------------------------------------------------------------------------------------------------------------------------+
      | name                                   | address                                | state     | health      | hosting             |
      +---------------------------------------------------------------------------------------------------------------------------------+
      | "0908819d-238a-473d-9877-5cc406050ea2" | "server4.neo4j.svc.cluster.local:7687" | "Free"    | "Available" | ["system"]          |
      | "19817354-5cd1-4579-8c45-8b897808fdb4" | "server2.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
      | "b3c91592-1806-41d0-9355-8fc6ba236043" | "server3.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
      | "eefd7216-6096-46f5-9c41-a74f79684172" | "server1.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
      +---------------------------------------------------------------------------------------------------------------------------------+
  3. Using its name, enable server4 to use it in the cluster:

    ENABLE SERVER "0908819d-238a-473d-9877-5cc406050ea2";
  4. Run SHOW SERVERS; again to verify that server4 is enabled:

    SHOW SERVERS;
    +---------------------------------------------------------------------------------------------------------------------------------+
    | name                                   | address                                | state     | health      | hosting             |
    +---------------------------------------------------------------------------------------------------------------------------------+
    | "0908819d-238a-473d-9877-5cc406050ea2" | "server4.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system"]          |
    | "19817354-5cd1-4579-8c45-8b897808fdb4" | "server2.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
    | "b3c91592-1806-41d0-9355-8fc6ba236043" | "server3.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
    | "eefd7216-6096-46f5-9c41-a74f79684172" | "server1.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
    +---------------------------------------------------------------------------------------------------------------------------------+

Add a new server and enable it automatically

This feature is available from Neo4j 5.20.

You can enable a new server automatically when it joins the cluster by setting the neo4j.operations.enableServer value to true in the values.yaml file or using the --set flag when running helm install. This feature is useful when you want to add a new server to the cluster and enable it without manual intervention.

  1. Install server4 using one of the following options:

    • Run helm install with the same value for neo4j.name as your existing cluster:

      helm install server4 neo4j --set neo4j.edition=enterprise --set neo4j.acceptLicenseAgreement=yes --set volumes.data.mode=defaultStorageClass --set neo4j.password="password" --set neo4j.minimumClusterSize=3 --set neo4j.name=my-cluster --set neo4j.operations.enableServer=true --set image="neo4j/helm-charts-operations:5.20.0" --set protocol="neo4j"
    • Use a values.yaml file to set the values for the new server and the neo4j/neo4j Helm chart to install the new server.

      1. Ensure that the neo4j.name value is the same as your existing cluster and the neo4j.operations.enableServer is set to true.

        neo4j:
          name: "my-cluster"
          minimumClusterSize: 3
          resources:
            cpu: "0.5"
            memory: "2Gi"
          password: "my-password"
          edition: "enterprise"
          acceptLicenseAgreement: "yes"
        
        volumes:
          data:
            mode: "dynamic"
            dynamic:
              # * premium-rwo provisions SSD disks (recommended)
              # * standard-rwo provisions balanced SSD-backed disks
              # * standard provisions HDD disks
              storageClassName: premium-rwo
        
        operations:
              enableServer: false
              image: "neo4j/helm-charts-operations:5.20.0"
              # protocol can be "neo4j or "neo4j+ssc" or "neo4j+s". Default set to neo4j
              # Note: Do not specify bolt protocol here...it will FAIL.
              protocol: "neo4j"
              labels: {}

        For all possible configuration options and more information on customizing your deployment, see Customizing a Neo4j Helm chart. For more information on how to create a values.yaml file and install Neo4j cluster servers, see Create Helm deployment values files and Install Neo4j cluster servers.

      2. Run helm install with the modified deployment values.yaml file and the Neo4j Helm chart to apply the changes.

        helm install server4 neo4j -f values.yaml

        When the new server joins the cluster, it will automatically be enabled and ready to host databases.

  2. Using Cypher Shell (or Neo4j Browser), verify that the new server is in the state Enabled:

    1. Access the Cypher Shell on server1:

      kubectl exec -ti server1-0 -- cypher-shell -u neo4j -p password -d neo4j
    2. Run SHOW SERVERS; to verify that server4 is enabled:

      SHOW SERVERS;
      +---------------------------------------------------------------------------------------------------------------------------------+
      | name                                   | address                                | state     | health      | hosting             |
      +---------------------------------------------------------------------------------------------------------------------------------+
      | "0908819d-238a-473d-9877-5cc406050ea2" | "server4.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system"]          |
      | "19817354-5cd1-4579-8c45-8b897808fdb4" | "server2.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
      | "b3c91592-1806-41d0-9355-8fc6ba236043" | "server3.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
      | "eefd7216-6096-46f5-9c41-a74f79684172" | "server1.neo4j.svc.cluster.local:7687" | "Enabled" | "Available" | ["system", "neo4j"] |
      +---------------------------------------------------------------------------------------------------------------------------------+

Change the database topology

Notice in the output that although server4 is now enabled, it is not hosting the neo4j database. You need to change the database topology to also use the new server.

  1. Alter the neo4j database topology to be hosted on three primary and one secondary servers:

    ALTER DATABASE neo4j SET TOPOLOGY 3 PRIMARIES 1 SECONDARY;
  2. Now run the SHOW DATABASES; command to verify the new topology:

    SHOW DATABASES;
    +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | name     | type       | aliases | access       | address                                | role        | writer | requestedStatus | currentStatus | statusMessage | default | home  | constituents |
    +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | "neo4j"  | "standard" | []      | "read-write" | "server2.neo4j.svc.cluster.local:7687" | "primary"   | TRUE   | "online"        | "online"      | ""            | TRUE    | TRUE  | []           |
    | "neo4j"  | "standard" | []      | "read-write" | "server4.neo4j.svc.cluster.local:7687" | "secondary" | FALSE  | "online"        | "online"      | ""            | TRUE    | TRUE  | []           |
    | "neo4j"  | "standard" | []      | "read-write" | "server3.neo4j.svc.cluster.local:7687" | "primary"   | FALSE  | "online"        | "online"      | ""            | TRUE    | TRUE  | []           |
    | "neo4j"  | "standard" | []      | "read-write" | "server1.neo4j.svc.cluster.local:7687" | "primary"   | FALSE  | "online"        | "online"      | ""            | TRUE    | TRUE  | []           |
    | "system" | "system"   | []      | "read-write" | "server2.neo4j.svc.cluster.local:7687" | "primary"   | FALSE  | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
    | "system" | "system"   | []      | "read-write" | "server4.neo4j.svc.cluster.local:7687" | "primary"   | FALSE  | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
    | "system" | "system"   | []      | "read-write" | "server3.neo4j.svc.cluster.local:7687" | "primary"   | TRUE   | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
    | "system" | "system"   | []      | "read-write" | "server1.neo4j.svc.cluster.local:7687" | "primary"   | FALSE  | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
    +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

    Note that server4 now hosts the neo4j database with the secondary role.