New to KubeDB? Please start here.

Horizontal Scaling Milvus

This guide will show you how to use the KubeDB Ops-manager operator to horizontally scale the roles of a distributed Milvus database.

Horizontal scaling is distributed-only. A Standalone Milvus is a single all-in-one workload (one PetSet, one replica) and cannot be horizontally scaled. To scale out, deploy Milvus in Distributed mode.

Before You Begin

Note: The yaml files used in this tutorial are stored in docs/guides/milvus/scaling/horizontal-scaling/yamls folder in GitHub repository kubedb/docs.

Deploy a Distributed Milvus

Deploy the distributed quickstart manifest (milvus-cluster) and wait until it is Ready. By default each role runs a single replica.

If you deleted a Milvus of the same name in an earlier guide, delete its object-storage prefix first, as shown in Prepare Dependencies. Otherwise the new database can hang in Provisioning.

$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.10.12/docs/guides/milvus/quickstart/yamls/distributed.yaml
milvus.kubedb.com/milvus-cluster created

$ kubectl get milvuses.kubedb.com -n demo milvus-cluster -w

$ kubectl get petset milvus-cluster-proxy milvus-cluster-streamingnode -n demo -o custom-columns=NAME:.metadata.name,REPLICAS:.spec.replicas
NAME                           REPLICAS
milvus-cluster-proxy           1
milvus-cluster-streamingnode   1

Apply the HorizontalScaling OpsRequest

The sample scales proxy and streamingnode from 1 to 2 replicas.

horizontal-scaling-distributed.yaml

apiVersion: ops.kubedb.com/v1alpha1
kind: MilvusOpsRequest
metadata:
  name: milvus-hscale-up
  namespace: demo
spec:
  type: HorizontalScaling
  databaseRef:
    name: milvus-cluster
  horizontalScaling:
    topology:
      proxy: 2
      streamingnode: 2

Here, spec.horizontalScaling.topology carries the desired replica count per role. The API also accepts mixcoord, querynode and dataNode; this sample only scales proxy and streamingnode, but the other roles are scaled the same way.

The data node key is dataNode (camelCase) in spec.horizontalScaling.topology, unlike every other role key and unlike spec.verticalScaling, where it is datanode. datanode is rejected here as an unknown field.

$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.10.12/docs/guides/milvus/scaling/horizontal-scaling/yamls/horizontal-scaling-distributed.yaml
milvusopsrequest.ops.kubedb.com/milvus-hscale-up created

Watch Progress and Verify

$ kubectl get milvusopsrequest milvus-hscale-up -n demo
NAME               TYPE                STATUS       AGE
milvus-hscale-up   HorizontalScaling   Successful   57s
$ kubectl describe milvusopsrequest milvus-hscale-up -n demo
...
Status:
  Conditions:
    Message:  Milvus ops-request has started to horizontally scale the Milvus nodes
    Reason:   HorizontalScaling
    Type:     HorizontalScaling
    Message:  Successfully Scaled Up proxy
    Reason:   ScaleUpProxy
    Type:     ScaleUpProxy
    Message:  pod readyproxy; ConditionStatus:True; PodName:milvus-cluster-proxy-1
    Type:     PodReadyproxy--milvus-cluster-proxy-1
    Message:  Successfully Scaled Up streamingnode
    Reason:   ScaleUpStreamingNode
    Type:     ScaleUpStreamingNode
  Phase:      Successful

Both roles now run two replicas:

$ kubectl get petset milvus-cluster-proxy milvus-cluster-streamingnode -n demo -o custom-columns=NAME:.metadata.name,REPLICAS:.spec.replicas
NAME                           REPLICAS
milvus-cluster-proxy           2
milvus-cluster-streamingnode   2

$ kubectl get pods -n demo -l app.kubernetes.io/instance=milvus-cluster | grep -E 'proxy|streamingnode'
milvus-cluster-proxy-0           1/1     Running   0          70s
milvus-cluster-proxy-1           1/1     Running   0          39s
milvus-cluster-streamingnode-0   1/1     Running   0          119s
milvus-cluster-streamingnode-1   1/1     Running   0          18s

Scale Down

Scaling down works the same way — set lower replica counts in spec.horizontalScaling.topology. horizontal-scaling-down-distributed.yaml scales both roles back to 1:

apiVersion: ops.kubedb.com/v1alpha1
kind: MilvusOpsRequest
metadata:
  name: milvus-hscale-down
  namespace: demo
spec:
  type: HorizontalScaling
  databaseRef:
    name: milvus-cluster
  horizontalScaling:
    topology:
      proxy: 1
      streamingnode: 1
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.10.12/docs/guides/milvus/scaling/horizontal-scaling/yamls/horizontal-scaling-down-distributed.yaml
milvusopsrequest.ops.kubedb.com/milvus-hscale-down created

$ kubectl get milvusopsrequest milvus-hscale-down -n demo

When a streamingnode is removed, its PVC is deleted too. Right after a scale-down reports Successful, the Milvus object can show Critical for about a minute while Milvus rebalances, then returns to Ready.

Cleaning up

$ kubectl delete milvusopsrequest -n demo milvus-hscale-up milvus-hscale-down
$ kubectl patch -n demo milvus.kubedb.com milvus-cluster -p '{"spec":{"deletionPolicy":"WipeOut"}}' --type="merge"
$ kubectl delete milvus.kubedb.com -n demo milvus-cluster
$ kubectl delete ns demo

Next Steps