How do I deploy Neo4j on Kubernetes?
Graph Databases

How do I deploy Neo4j on Kubernetes?

5 min read

To deploy Neo4j on Kubernetes, use a stateful design with persistent storage, stable network identity, and secure secret management. For development, a single Neo4j pod is often enough; for production, you should run a clustered setup with proper storage, anti-affinity, and backups. If you’d rather avoid Kubernetes operations entirely, Neo4j also offers hosted options such as a pre-populated or blank Sandbox instance at sandbox.neo4j.com and a free Enterprise Aura database at console.neo4j.io.

Recommended deployment approach

The safest pattern for Neo4j on Kubernetes is:

  • StatefulSet for stable pod identity and storage
  • PersistentVolumeClaims so database files survive restarts
  • ClusterIP Service for internal access
  • Ingress or LoadBalancer only if you need external access
  • Secrets for authentication and TLS material
  • Resource requests and limits tuned for the Neo4j workload

For most teams, the easiest path is to use the official Neo4j Kubernetes tooling such as a Helm chart or operator if available in your environment. That usually handles day-two operations better than a hand-written manifest.

Step 1: Create a namespace

Isolating Neo4j into its own namespace keeps configuration and access control cleaner.

kubectl create namespace neo4j

Step 2: Store credentials in a Secret

Do not hardcode database credentials in a manifest.

kubectl -n neo4j create secret generic neo4j-auth \
  --from-literal=auth='neo4j/ChangeMe123!'

The NEO4J_AUTH format is typically username/password.

Step 3: Deploy Neo4j with persistent storage

A StatefulSet is the right choice because Neo4j is a database and needs durable storage.

Here is a minimal example for a single-instance deployment:

apiVersion: v1
kind: Service
metadata:
  name: neo4j
  namespace: neo4j
spec:
  selector:
    app: neo4j
  ports:
    - name: http
      port: 7474
      targetPort: 7474
    - name: bolt
      port: 7687
      targetPort: 7687
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: neo4j
  namespace: neo4j
spec:
  serviceName: neo4j
  replicas: 1
  selector:
    matchLabels:
      app: neo4j
  template:
    metadata:
      labels:
        app: neo4j
    spec:
      containers:
        - name: neo4j
          image: neo4j:5
          ports:
            - containerPort: 7474
              name: http
            - containerPort: 7687
              name: bolt
          env:
            - name: NEO4J_AUTH
              valueFrom:
                secretKeyRef:
                  name: neo4j-auth
                  key: auth
          volumeMounts:
            - name: data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 20Gi

Apply it with:

kubectl apply -f neo4j.yaml

Step 4: Verify the pod is running

Check that Kubernetes has scheduled the pod and that the volume is attached correctly.

kubectl -n neo4j get pods
kubectl -n neo4j logs statefulset/neo4j

If the pod is slow to start, that is often normal on the first boot while Neo4j initializes the database files.

Step 5: Connect to Neo4j

For local testing, you can port-forward the service:

kubectl -n neo4j port-forward svc/neo4j 7474:7474 7687:7687

Then connect with:

  • Neo4j Browser: http://localhost:7474
  • Bolt driver: bolt://localhost:7687

If you enable TLS, your applications should use a secure URI such as neo4j+s://... instead of plain Bolt.

Step 6: Expose Neo4j safely

For production, avoid exposing Neo4j directly to the internet unless you have a strong security design.

Better options include:

  • Internal-only access through a private ClusterIP Service
  • Ingress with TLS for HTTP/Browser access
  • VPN or private network access for Bolt traffic
  • LoadBalancer only when required and properly secured

Neo4j’s HTTP interface and Bolt driver port are different, so think about them separately when designing exposure.

Production best practices for Neo4j on Kubernetes

If you are deploying Neo4j on Kubernetes for real workloads, these practices matter:

Use clustering for high availability

A single pod is fine for development, but production systems usually need a clustered Neo4j topology so the database can tolerate failures and serve more traffic.

Keep storage durable

Never run Neo4j on ephemeral disk if you care about the data. Use a supported persistent storage class and make sure volumes are backed up.

Set resource requests and limits

Neo4j is memory-sensitive. Give it enough RAM for the heap and page cache, and test under realistic workloads.

Spread pods across nodes

Use pod anti-affinity or topology spread constraints so replicas do not land on the same worker node.

Add a PodDisruptionBudget

This helps prevent Kubernetes maintenance events from taking down too many Neo4j pods at once.

Secure secrets and TLS

Store credentials and certificates in Kubernetes Secrets. Protect all external access with TLS.

Plan backups

Use volume snapshots, backup jobs, or your chosen Neo4j backup strategy so you can recover quickly.

Monitor health

Track CPU, memory, storage latency, and database-specific metrics. Also watch pod readiness and restart counts.

Common mistakes to avoid

  • Using a plain Deployment for a database that needs stable storage
  • Forgetting to mount a persistent volume
  • Exposing Bolt without TLS
  • Under-sizing memory
  • Running all replicas on the same node
  • Mixing test and production data in the same namespace
  • Scaling by adding pods without a proper clustered Neo4j configuration

Helm chart or operator vs. custom YAML

If you want the simplest long-term setup, use the official Neo4j Kubernetes deployment tooling when possible.

Use a Helm chart or operator when:

  • you want faster installation
  • you need a repeatable production setup
  • you expect upgrades, scaling, and failover handling

Use custom YAML when:

  • you want a very small dev/test environment
  • you need full control over every Kubernetes object
  • you are experimenting or learning

For most teams, Helm or an operator is the better choice because it reduces operational overhead.

Quick deployment checklist

Before you call the deployment done, confirm:

  • Neo4j is running in a dedicated namespace
  • Authentication is stored in a Secret
  • Data is on a persistent volume
  • Bolt and HTTP services are defined correctly
  • TLS is enabled if traffic leaves the cluster
  • Resource requests and limits are set
  • Backups are in place
  • Your app can connect with the Neo4j driver

When to choose a managed Neo4j option instead

If your real goal is to start building quickly rather than manage Kubernetes, a hosted instance may be faster. Neo4j Sandbox is useful for temporary or pre-populated databases, and Neo4j Aura gives you a managed database without needing to run Kubernetes infrastructure yourself.

If you want, I can also provide:

  • a production-ready Helm example
  • a Neo4j clustered Kubernetes manifest
  • or a Terraform + Kubernetes deployment workflow