Home / AI & GenAI / Vector Databases

AI & GenAIRunbookIntermediate

Milvus backup and restore with milvus-backup: configuration, scheduled backups, restoring with a suffix, and drills

Back up Milvus collections to object storage with the milvus-backup tool, restore them under new names to verify before switching, move data between clusters, and run the whole thing as a scheduled, monitored job.

Deepak Bhardwaj5 min read

Applies toMilvus 2.4-2.6 (standalone or distributed), milvus-backup CLI (zilliztech/milvus-backup); bucket defaults differ between Docker Compose and Helm installs

What milvus-backup does

milvus-backup reads collection metadata from Milvus and copies the collection's segment files from Milvus's object storage to a backup location (same bucket under another prefix, or another bucket). Restore creates collections again and imports those files. It doesn't stop Milvus.

It's not a replacement for being able to rebuild from source documents. It's the fast path back after a delete, a bad migration or a lost cluster.

Step 1: get the tool and a config

# download a release binary for your OS from the project's GitHub releases page
cp configs/backup.yaml backup.yaml

Key settings in backup.yaml:

configVersion: v2
milvus:
  grpc:
    address: milvus.milvus.svc.cluster.local:19530
  storage:                       # where Milvus keeps its data - must match Milvus config exactly
    provider: minio              # minio | aws | azure | gcp ...
    address: milvus-minio.milvus.svc.cluster.local
    port: 9000
    bucketName: milvus-bucket    # Helm default; Docker Compose default is a-bucket
    rootPath: file               # Helm default; Docker Compose default is files
backup:
  storage:                       # where backups go; unset values inherit from milvus.storage
    bucketName: milvus-backups
    rootPath: backup

Credentials are better passed as environment or --set values than stored in the file:

milvus-backup --set MILVUS_USER=root --set MILVUS_PASSWORD="$MILVUS_PASSWORD" check
milvus-backup config show        # print the resolved configuration

Warning

The most common failure is a wrong bucketName or rootPath for the Milvus storage. The tool then "backs up" collections without finding their files. Copy the values from the Milvus configmap (minio.bucketName, minio.rootPath), don't guess.

Step 2: run check

milvus-backup check

It validates the connection to Milvus and both storage locations. Fix every error here before relying on backups.

Step 3: create a backup

milvus-backup create -n kb_20261028_0200
milvus-backup list
milvus-backup get -n kb_20261028_0200     # use --help to confirm flags for your version

Back up specific collections or databases with the filter options (milvus-backup create --help shows them for your version). Backing up only production collections keeps backups small and fast.

Data in growing (unflushed) segments may not be included unless it's flushed first; recent versions of the tool handle flushing, but for a clean point-in-time copy flush first:

client.flush(collection_name="kb_chunks")

Step 4: restore under a new name and verify

Never restore over the live collection first. Restore with a suffix:

milvus-backup restore -n kb_20261028_0200 -s _recover

Or rename to another database/collection:

milvus-backup restore -n kb_20261028_0200 -r default.kb_chunks:restore.kb_chunks

Then build indexes if the restore didn't include them, load and check:

client.get_collection_stats(collection_name="kb_chunks_recover")      # row_count
client.list_indexes(collection_name="kb_chunks_recover")
client.load_collection(collection_name="kb_chunks_recover")
Verification Pass condition
Row count Matches the source at backup time
Index Present, same type and params
Sample search Known queries return the expected doc_ids
Filters Scalar fields present and filterable

Step 5: switch over with an alias

If applications query an alias (recommended), switching is one call:

client.alter_alias(collection_name="kb_chunks_recover", alias="kb_chunks_live")

If they use the physical name, you'll need to drop and restore with the original name, which means downtime. Move to aliases at the next change.

Then replay any documents changed after the backup time from your ingestion system.

Step 6: restore to another cluster (DR or migration)

Point a second backup.yaml at the target cluster's Milvus and storage, with backup.storage pointing at the bucket holding the backups (replicated to the DR region if needed):

milvus-backup --config backup-dr.yaml list
milvus-backup --config backup-dr.yaml restore -n kb_20261028_0200

Cross-cloud transfers depend on the tool's transfer mode and network access between storages; test it once before you need it.

Step 7: schedule and monitor

Run as a Kubernetes CronJob:

apiVersion: batch/v1
kind: CronJob
metadata: { name: milvus-backup, namespace: milvus }
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      backoffLimit: 1
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: backup
            image: <your-registry>/milvus-backup:<pinned-version>
            command: ["/bin/sh", "-c"]
            args: ["milvus-backup create -n kb_$(date +%Y%m%d_%H%M)"]
            envFrom: [{ secretRef: { name: milvus-backup-credentials } }]
            volumeMounts: [{ name: cfg, mountPath: /app/configs }]
          volumes: [{ name: cfg, configMap: { name: milvus-backup-config } }]
  • Alert when the job fails or hasn't succeeded in 26 hours.
  • Delete old backups with a retention job (milvus-backup delete) or object storage lifecycle rules on the backup prefix.
  • Keep backups in a different bucket (and ideally account/subscription) from the Milvus data.

Recovery decision table

Incident Path
Dropped or corrupted collection Restore with suffix, verify, alias switch
Bad data for days Older backup + replay, or rebuild from source
Cluster lost Restore all collections on a new cluster from replicated backups
Migration to a new cluster/version Backup on old, restore on new (check version compatibility notes)

Prevent it next time

  • Copy storage settings from the Milvus configmap into backup.yaml and run check in CI.
  • Use aliases for every collection the application reads.
  • Store backups outside the Milvus bucket and outside the cluster's failure domain.
  • Run a timed restore drill every quarter and record the result.