Jesse A. Green / notebook

Milvus User Guide

Generated June 2026 from milvus-io/milvus at d9bbbc1

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Milvus is a high-performance, open-source vector database built for scale. It stores the vector embeddings produced by AI models alongside scalar metadata, and lets you run similarity search, filtered search, full-text search, and hybrid search over billions of vectors with low latency. Written in Go and C++ with hardware acceleration for CPU and GPU, Milvus powers applications such as retrieval-augmented generation (RAG), semantic search, recommendation systems, image and video search, and anomaly detection.

This guide shows you how to install Milvus, connect to it, model your data, ingest vectors, build indexes, and run searches. It is organized by user journey: start with Quick Start, deploy with Installation, then work through Everyday Usage, Search Workflows, and Advanced Features. Deep architecture, the complete configuration reference, deployment topologies, and security hardening live in the companion Admin Guide.

Note

Milvus exposes three client surfaces for the same server: the gRPC API (default port 19530), a RESTful API (/v2/vectordb/... on the same port), and official SDKs for Python (pymilvus), Go (shipped in this repository under client/), Java, and Node.js. Examples in this guide use Python (pymilvus) and the in-repository Go SDK.


1. Quick Start

The fastest way to try Milvus is Milvus Lite, an embedded build that runs inside your Python process and persists to a local file — no server, no Docker.

Python (Milvus Lite)

pip install -U pymilvus
from pymilvus import MilvusClient

# A local file name turns on Milvus Lite (embedded, no server).
client = MilvusClient("milvus_demo.db")

client.create_collection(
    collection_name="demo_collection",
    dimension=768,  # dimension of the vectors you will store
)

# Insert data: each row needs an "id", a "vector", and any extra fields.
res = client.insert(collection_name="demo_collection", data=data)

# Search with one or more query vectors.
res = client.search(
    collection_name="demo_collection",
    data=query_vectors,           # a list of one or more query vectors
    limit=2,                      # top-K results to return
    output_fields=["text", "subject"],
)

Python (remote server)

from pymilvus import MilvusClient

client = MilvusClient(
    uri="http://localhost:19530",
    token="root:Milvus",          # default credentials, change in production
)

Go (in-repo SDK)

import (
    "context"
    "github.com/milvus-io/milvus/client/v2/milvusclient"
)

ctx := context.Background()
cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
    Address:  "localhost:19530",
    Username: "root",
    Password: "Milvus",
})
if err != nil {
    // handle error
}
defer cli.Close(ctx)

Tip

Milvus Lite is ideal for prototyping, unit tests, and notebooks. When your dataset or traffic grows, move to Standalone (single container) or a distributed cluster with no code changes — only the connection URI changes. See Installation.

Important

The vector dimension is fixed when you create a collection and cannot be changed afterward. It must exactly match the output dimension of the embedding model you use (for example, 768 for many sentence-transformer models, 1536 for OpenAI text-embedding-3-small).


2. Installation

Milvus ships in four deployment shapes. Choose by scale and operational appetite.

Deployment What it is Best for
Milvus Lite Embedded library inside your Python process; persists to a local file Prototyping, notebooks, tests, small local data
Standalone A single Docker container plus etcd and MinIO dependencies Single-machine production, dev/staging, up to tens of millions of vectors
Distributed cluster Separately scaled coordinator and worker services on Kubernetes Billions of vectors, high availability, elastic scale
Zilliz Cloud Fully managed Milvus (not part of this repository) Zero-ops production

This User Guide focuses on Milvus Lite and Standalone. Cluster topology, sizing, and the full container/Helm reference are covered in the Admin Guide.

2.1 Requirements

For the Standalone Docker deployment you need:

  • [ ] Docker Engine and the Docker Compose plugin
  • [ ] At least 4 CPU cores and 8 GB RAM (more for larger datasets)
  • [ ] Sufficient free disk for object storage (vectors, indexes, and logs)

Note

Standalone runs three containers: milvus-etcd (metadata + service discovery), milvus-minio (object storage for vector and index files), and milvus-standalone (the Milvus server itself). All three are defined in the official deployments/docker/standalone/docker-compose.yml.

2.2 Install Standalone with Docker Compose

The official Compose file launches the full standalone stack:

services:
  etcd:
    container_name: milvus-etcd
    image: quay.io/coreos/etcd:v3.5.25
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296
      - ETCD_SNAPSHOT_COUNT=50000
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
    command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd

  minio:
    container_name: milvus-minio
    image: minio/minio:RELEASE.2024-05-28T17-19-04Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    ports:
      - "9001:9001"
      - "9000:9000"
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
    command: minio server /minio_data --console-address ":9001"

  standalone:
    container_name: milvus-standalone
    image: milvusdb/milvus:v3.0-beta
    command: ["milvus", "run", "standalone"]
    security_opt:
      - seccomp:unconfined
    environment:
      MINIO_REGION: us-east-1
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - "etcd"
      - "minio"

Bring the stack up:

sudo docker compose up -d
Creating milvus-etcd  ... done
Creating milvus-minio ... done
Creating milvus-standalone ... done

Verify the server is healthy:

curl -f http://localhost:9091/healthz
OK

Tip

Port 19530 serves both the gRPC API and the RESTful API for your clients. Port 9091 serves the health check (/healthz), Prometheus metrics (/metrics), and the built-in Web UI. The MinIO console is on 9001.

Caution

The default credentials baked into a fresh install are username root and password Milvus. Change them before exposing Milvus to any untrusted network. See Authentication and the Admin Guide security chapter.

2.3 The milvus binary and server roles

Inside the container, the milvus binary is the single entry point for every server role. Standalone is simply the all-in-one role:

milvus run standalone

The binary accepts the following top-level commands:

Command Purpose
milvus run <server type> [flags] Start a Milvus server of the given type
milvus stop <server type> [flags] Stop a running Milvus server
milvus mck run [flags] Run a metadata/data consistency check
milvus mck cleanTrash [flags] Clean inconsistent (orphaned) data found by mck
milvus dry-run <server type> Validate startup without running the server

The valid server types are standalone, mixture, mixcoord, rootcoord, querycoord, datacoord, proxy, querynode, datanode, streamingnode, cdc, and embedded. For everyday use you only need standalone; the individual roles are for distributed deployments and are detailed in the Admin Guide.

Note

The mck (Milvus Consistency Check) command is an operator tool that scans etcd and object storage for orphaned task and segment references. It is covered in the Admin Guide under operations; most users never need it.

2.4 Stop and remove

sudo docker compose down                 # stop containers
sudo rm -rf volumes                       # delete persisted data (irreversible)

Warning

rm -rf volumes permanently deletes all collections, vectors, indexes, and metadata. There is no undo. Back up first if the data matters — see the Admin Guide on snapshots and RBAC backup.


3. Core Concepts

A few concepts recur throughout this guide. Skim them now; later sections assume them.

Collection : The top-level container for your data, analogous to a table in a relational database. A collection has a fixed schema of fields.

Schema : The set of fields in a collection. Exactly one field is the primary key. At least one field is a vector field. Other fields hold scalar metadata.

Entity : A single row — one primary key, one or more vectors, and the scalar field values.

Field : A typed column. Vector fields hold embeddings; scalar fields hold filterable metadata.

Index : A data structure built over a vector or scalar field to accelerate search. You choose an index type and a metric type per vector field.

Partition : A horizontal slice of a collection. Searching a single partition is faster than searching the whole collection. A special partition key field can auto-route entities to partitions.

Database : A namespace that groups collections, enabling multi-tenancy within one Milvus instance.

Load / Release : A collection must be loaded into memory (on query nodes) before it can be searched, and can be released to free memory.

Consistency level : How fresh search results are guaranteed to be — Strong, Bounded (default), Session, or Eventually. See Consistency Levels.

Important

The lifecycle is always: create collection → insert data → create index → load → search. You cannot search a collection that has not been loaded, and load requires an index on every vector field (or an AUTOINDEX).


4. Data Modeling

4.1 Field data types

Milvus supports the following field types (Go SDK names from client/entity/field.go; the Python and REST names are equivalent):

Category Types
Boolean Bool
Integer Int8, Int16, Int32, Int64
Floating point Float, Double
String VarChar (requires max_length)
Structured JSON, Array (typed elements), Geometry
Dense vectors FloatVector, Float16Vector, BFloat16Vector, Int8Vector, BinaryVector
Sparse vectors SparseFloatVector

Note

The primary key field must be Int64 or VarChar. A collection must have at least one vector field and may have several (multi-vector collections enable hybrid search across modalities).

4.2 Create a collection (quick schema)

For simple cases, let Milvus infer a minimal schema from a dimension and use AUTOINDEX:

client.create_collection(
    collection_name="demo_collection",
    dimension=768,                 # creates an Int64 primary key "id" + FloatVector "vector"
    metric_type="COSINE",          # distance metric for search
    consistency_level="Bounded",   # default
)

4.3 Create a collection (explicit schema)

For production, define every field explicitly:

Python

from pymilvus import MilvusClient, DataType

schema = MilvusClient.create_schema(
    auto_id=False,
    enable_dynamic_field=True,
)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=768)
schema.add_field("text", DataType.VARCHAR, max_length=2048)
schema.add_field("subject", DataType.VARCHAR, max_length=256)

client.create_collection(
    collection_name="articles",
    schema=schema,
    consistency_level="Bounded",
)

Go

import "github.com/milvus-io/milvus/client/v2/entity"

schema := entity.NewSchema().
    WithField(entity.NewField().WithName("id").WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true)).
    WithField(entity.NewField().WithName("vector").WithDataType(entity.FieldTypeFloatVector).WithDim(768)).
    WithField(entity.NewField().WithName("text").WithDataType(entity.FieldTypeVarChar).WithMaxLength(2048))

err := cli.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("articles", schema))

Tip

Set auto_id=True to have Milvus generate primary keys for you on insert. Set enable_dynamic_field=True to allow each entity to carry extra, un-declared JSON fields — useful when your metadata schema is not fixed.

4.4 Dynamic fields

When enable_dynamic_field=True, any keys you insert that are not declared in the schema are stored in a hidden JSON field. You can filter and even index them by JSON path:

index_params.add_index(
    field_name="overview",          # a key inside the dynamic field
    index_type="AUTOINDEX",         # AUTOINDEX or INVERTED for JSON-path indexing
    index_name="overview_index",
    params={
        "json_cast_type": "varchar",
        "json_path": "overview",
    },
)

4.5 Schema limits

These defaults come from the server configuration and bound what a schema may declare:

Limit Default Config key
Max name/alias/field-name length 255 proxy.maxNameLength
Max fields per collection 64 proxy.maxFieldNum
Max vector fields per collection 10 proxy.maxVectorFieldNum
Max shards per collection 16 proxy.maxShardNum
Max vector dimension 32768 proxy.maxDimension
Max partitions per collection 1024 rootCoord.maxPartitionNum
Max collections 65536 quotaAndLimits.limits.maxCollectionNum
Max databases 64 rootCoord.maxDatabaseNum

Warning

Setting maxFieldNum ≥ 64 is strongly discouraged by the project. Wide schemas degrade write and query performance. Prefer the dynamic field for sparse, optional metadata.


5. Ingesting Data

5.1 Insert

Insert adds new entities. Each row is a mapping of field name to value:

Python

data = [
    {"id": 1, "vector": [0.1, 0.2, ...], "text": "hello", "subject": "greeting"},
    {"id": 2, "vector": [0.3, 0.1, ...], "text": "world", "subject": "greeting"},
]
res = client.insert(collection_name="articles", data=data)
print(res["insert_count"])

Go

_, err := cli.Insert(ctx, milvusclient.NewColumnBasedInsertOption("articles").
    WithInt64Column("id", []int64{1, 2}).
    WithFloatVectorColumn("vector", 768, [][]float32{vec1, vec2}).
    WithVarcharColumn("text", []string{"hello", "world"}))

5.2 Upsert

Upsert inserts new entities or replaces existing ones with the same primary key:

client.upsert(collection_name="articles", data=data)

Note

Upsert requires a non-auto primary key (you must supply the key). It is implemented as a delete-then-insert, so the replaced entity's old version is removed.

5.3 Delete

Delete by primary key list or by a boolean filter expression:

# By primary keys
client.delete(collection_name="articles", ids=[1, 2, 3])

# By filter expression
client.delete(collection_name="articles", filter="subject == 'greeting'")

5.4 Flush

Insertions are buffered and periodically sealed into persistent segments automatically. Call Flush to force the current buffer to be sealed and persisted immediately:

client.flush(collection_name="articles")

Caution

Do not call flush after every small insert. Frequent manual flushes create many tiny segments, which hurts search performance until compaction merges them. Let Milvus seal segments on its own schedule; flush only when you need a hard durability boundary (for example, before a backup). Flush is rate-limited (quotaAndLimits.flushRate).

5.5 Bulk import

For large offline loads, use the import API rather than streaming inserts. Import ingests files (Parquet, JSON, or NumPy) already staged in object storage and builds segments in bulk — far more efficient than row-by-row Insert for millions of rows. Import behavior is governed by dataCoord.import.* and dataNode.import.* (see the Admin Guide).

Tip

Rule of thumb: use Insert/Upsert for live, incremental writes; use import for the initial backfill of an existing dataset.


6. Indexing

A vector index trades a small amount of recall for a large speedup. You must build an index (or use AUTOINDEX) before a collection can be loaded and searched.

6.1 Build a vector index

Python

index_params = client.prepare_index_params()
index_params.add_index(
    field_name="vector",
    index_type="HNSW",
    metric_type="COSINE",
    params={"M": 16, "efConstruction": 200},
)
client.create_index(collection_name="articles", index_params=index_params)

Go

idx := index.NewHNSWIndex(entity.COSINE, 16, 200)
_, err := cli.CreateIndex(ctx, milvusclient.NewCreateIndexOption("articles", "vector", idx))

6.2 Vector index types

The in-repo Go SDK (client/index/common.go) defines these index types:

Index type Family Notes
FLAT Brute force Exact search, 100% recall, no build needed
IVF_FLAT Inverted file Balanced speed/recall
IVF_SQ8 Inverted file + scalar quantization Lower memory
IVF_PQ Inverted file + product quantization Much lower memory, some recall loss
IVF_RABITQ Inverted file + RaBitQ Compact quantized variant
HNSW Graph High recall, high QPS, higher memory
IVF_HNSW Hybrid IVF coarse + HNSW refine
SCANN Quantized Fast, good recall density
DISKANN Disk-resident graph Billion-scale on SSD, lower memory footprint
AUTOINDEX Auto Milvus picks parameters for you
MINHASH_LSH LSH MinHash similarity
BIN_FLAT, BIN_IVF_FLAT Binary For BinaryVector fields
SPARSE_INVERTED_INDEX, SPARSE_WAND Sparse For SparseFloatVector (e.g. BM25/SPLADE)
GPU_IVF_FLAT, GPU_IVF_PQ, GPU_CAGRA, GPU_BRUTE_FORCE GPU Require a GPU build

Tip

If you are unsure, use AUTOINDEX. For most CPU workloads HNSW (best QPS/recall) or IVF_FLAT (simple, balanced) are safe defaults. For billion-scale data that does not fit in RAM, use DISKANN. Use GPU_CAGRA only on a GPU-enabled Milvus build.

6.3 Metric types

The metric must match how your embedding model was trained. Defined in client/entity/common.go:

Metric Use for
L2 Euclidean distance — dense float vectors
IP Inner product — dense float vectors
COSINE Cosine similarity — dense float vectors (normalized IP)
HAMMING, JACCARD, TANIMOTO Binary vectors
SUBSTRUCTURE, SUPERSTRUCTURE Chemical substructure search (binary)
BM25 Full-text search over sparse vectors
MHJACCARD MinHash Jaccard
MAX_SIM, MAX_SIM_COSINE, MAX_SIM_L2, MAX_SIM_IP, MAX_SIM_HAMMING, MAX_SIM_JACCARD Multi-vector (late-interaction, e.g. ColBERT/ColPali)

6.4 Scalar indexes

Index scalar fields to speed up filtered search. Types: STL_SORT (numeric), Trie and INVERTED (string), BITMAP (low-cardinality), and RTREE (geometry).

index_params.add_index(field_name="subject", index_type="INVERTED")

6.5 Manage indexes

client.list_indexes(collection_name="articles")
client.describe_index(collection_name="articles", index_name="vector")
client.drop_index(collection_name="articles", index_name="vector")

Note

To change an index, drop it and create a new one. The collection must be released before you can drop an index that backs a loaded vector field.


7. Connecting and Loading

7.1 Connect with authentication

The Go SDK ClientConfig (from client/milvusclient/client_config.go) accepts:

Field Meaning
Address Server address, e.g. localhost:19530
Username, Password Username/password authentication
APIKey API key (overrides username/password)
DBName Database to use for this connection
EnableTLSAuth Enable TLS transport security
DialOptions Extra gRPC dial options
RetryRateLimit Client-side retry behavior on rate-limit responses
cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
    Address:       "milvus.internal:19530",
    Username:      "root",
    Password:      "Milvus",
    DBName:        "default",
    EnableTLSAuth: true,
})

In Python, pass uri and token ("<user>:<password>" or an API key):

client = MilvusClient(uri="https://milvus.internal:19530", token="root:Milvus")

Note

Authentication is only enforced when the server has common.security.authorizationEnabled set to true. A default install accepts any credentials. Turning auth on is an administrator task — see the Admin Guide security chapter.

7.2 Load and release

Load a collection (or specific partitions) into query-node memory before searching:

client.load_collection(collection_name="articles")
state = client.get_load_state(collection_name="articles")   # check progress
# ... run searches ...
client.release_collection(collection_name="articles")        # free memory
client.load_partitions(collection_name="articles", partition_names=["2024"])
client.release_partitions(collection_name="articles", partition_names=["2024"])
client.refresh_load(collection_name="articles")   # reload after new data

Important

Loading consumes RAM proportional to the collection size and index. If a query node hits its memory water mark, loads are rejected and writes may be throttled. Release collections you are not actively querying, or scale out query nodes (Admin Guide).


8. Searching

Search finds the top-K nearest vectors to one or more query vectors:

Python

res = client.search(
    collection_name="articles",
    data=[query_vector],                # one or more query vectors
    limit=10,                           # top-K
    search_params={"metric_type": "COSINE", "params": {"ef": 64}},
    output_fields=["text", "subject"],  # scalar fields to return
    filter="subject == 'greeting'",     # optional metadata filter
)
for hit in res[0]:
    print(hit["id"], hit["distance"], hit["entity"]["text"])

Go

resultSets, err := cli.Search(ctx, milvusclient.NewSearchOption("articles", 10, []entity.Vector{
    entity.FloatVector(queryVector),
}).WithOutputFields("text", "subject").WithFilter("subject == 'greeting'"))

8.2 Consistency levels

Set per collection or per search. Higher consistency costs latency.

Level Guarantee
Strong Sees every write committed before the search started
Bounded Default. Sees writes up to a bounded staleness window
Session Sees this client's own writes immediately
Eventually Lowest latency; may miss the most recent writes
res = client.search(collection_name="articles", data=[query_vector],
                    limit=3, consistency_level="Strong")

Tip

Use Bounded for most search traffic, Session for read-after-write within a user session, and Strong only when you truly need the latest data (it forces a time-tick sync and adds latency).

The filter expression is a boolean predicate over scalar fields, evaluated before/with the vector search. Operators include ==, !=, >, <, >=, <=, in, like, and, or, not, and JSON/array accessors:

filter='(price < 100) and (category in ["books", "music"]) and (title like "intro%")'

8.4 Query (scalar retrieval) and Get

Query returns entities matching a filter with no vector involved; Get fetches by primary key:

client.query(collection_name="articles", filter="subject == 'greeting'",
            output_fields=["id", "text"], limit=100)

client.get(collection_name="articles", ids=[1, 2, 3], output_fields=["text"])

Return all vectors within a distance band rather than a fixed top-K, via radius and range_filter in search_params:

search_params = {"metric_type": "COSINE", "params": {"radius": 0.4, "range_filter": 0.8}}

8.6 Iterators

For paging through large result sets without holding everything in memory, use SearchIterator and QueryIterator (Go SDK client/milvusclient/iterator.go; Python search_iterator/query_iterator). Iterators fetch results in batches.

Return the best hit per group value (deduplicate by a scalar field) using group_by_field. The maximum group count is bounded by common.groupBy.maxGroups (default 100000).


When a collection has several vector fields (for example, a dense semantic vector and a sparse keyword vector), HybridSearch runs one search per field and fuses the rankings with a reranker:

from pymilvus import AnnSearchRequest, RRFRanker

dense_req = AnnSearchRequest(data=[dense_vec], anns_field="dense",
                            param={"metric_type": "COSINE"}, limit=20)
sparse_req = AnnSearchRequest(data=[sparse_vec], anns_field="sparse",
                            param={"metric_type": "BM25"}, limit=20)

res = client.hybrid_search(
    collection_name="articles",
    reqs=[dense_req, sparse_req],
    ranker=RRFRanker(),     # or WeightedRanker(...)
    limit=10,
    output_fields=["text"],
)

Note

Hybrid search combines, for example, semantic (dense) and lexical (sparse/BM25) relevance — the recommended pattern for RAG retrieval quality. The Go SDK exposes the equivalent HybridSearch method.

9.2 Full-text search with BM25

Milvus supports native full-text search: store text, let Milvus generate sparse BM25 vectors, and search with the BM25 metric over a SparseFloatVector field indexed with SPARSE_INVERTED_INDEX or SPARSE_WAND. Learned sparse embeddings such as SPLADE and BGE-M3 are also supported. Use RunAnalyzer to preview how text is tokenized:

client.run_analyzer(text="The quick brown fox", analyzer_params={"type": "english"})

9.3 Reranking with model providers

Milvus can call external reranker and embedding model providers (configured server-side under function.rerank and function.textEmbedding) — including OpenAI, Cohere, VoyageAI, Gemini, VertexAI, Bedrock, SiliconFlow, TEI, and vLLM. This lets you define embedding/rerank functions on a collection so Milvus generates vectors at insert/search time. Provider enablement and credentials are administrator settings (Admin Guide).


10. Organizing Data: Partitions, Databases, Aliases

10.1 Partitions

Partitions subdivide a collection so searches can target a slice:

client.create_partition(collection_name="articles", partition_name="2024")
client.list_partitions(collection_name="articles")
client.has_partition(collection_name="articles", partition_name="2024")
client.get_partition_stats(collection_name="articles", partition_name="2024")
client.drop_partition(collection_name="articles", partition_name="2024")

Then restrict a search to partitions with partition_names=["2024"].

10.2 Partition key

Instead of managing partitions manually, mark a scalar field as the partition key. Milvus hashes its value to auto-route each entity to a partition, giving you tenant isolation and faster filtered search without manual bookkeeping:

schema.add_field("tenant_id", DataType.VARCHAR, max_length=128, is_partition_key=True)

Tip

Partition-key isolation is the recommended multi-tenancy strategy when you have many tenants in one collection. For a handful of large tenants, use separate collections or databases instead.

10.3 Databases

Databases are namespaces for collections:

client.create_database(db_name="analytics")
client.use_database(db_name="analytics")
client.list_databases()
client.describe_database(db_name="analytics")
client.drop_database(db_name="analytics")

10.4 Aliases

An alias is a stable name that points at a collection — handy for zero-downtime reindexing (build a new collection, then repoint the alias):

client.create_alias(collection_name="articles_v2", alias="articles")
client.alter_alias(collection_name="articles_v3", alias="articles")
client.list_aliases(collection_name="articles_v3")
client.drop_alias(alias="articles")

11. Maintenance Operations You Can Trigger

These are user-callable operations (the heavier background work happens automatically):

Operation Method Effect
Flush flush Seal and persist the current insert buffer
Compact compact Merge small segments and purge deleted rows
Compaction state get_compaction_state Check a manual compaction's progress
Collection stats get_collection_stats Row count and storage stats
Load state get_load_state Whether/how much of a collection is loaded
Server version get_server_version The connected server's build version
client.compact(collection_name="articles")
print(client.get_collection_stats(collection_name="articles"))

Note

Manual compact is throttled by quotaAndLimits.compactionRate. Automatic compaction (dataCoord.compaction.enableAutoCompaction) handles routine merging; trigger manual compaction only after large deletes.


12. Snapshots and Replication (Overview)

The in-repo SDK exposes operations that admins typically drive, but which you may encounter:

  • Snapshots — create_snapshot, list_snapshots, restore_snapshot, and get_restore_snapshot_state capture and restore a point-in-time view of collection data.
  • Replication / CDC — get_replicate_info and create_replicate_stream support cross-cluster data replication (Change Data Capture). The cdc server role and Milvus CDC tool drive synchronization between clusters.

Configuration, topology, and operational guidance for these features are in the Admin Guide.


13. Access Control (RBAC) for Users

If your administrator has enabled authorization, you authenticate as a user that has been granted roles. As a user you may be permitted to manage your own credentials and, with sufficient privilege, users and roles:

client.create_user(user_name="alice", password="S3cret!")
client.update_password(user_name="alice", old_password="S3cret!", new_password="N3wS3cret!")
client.list_users()
client.create_role(role_name="reader")
client.grant_role(user_name="alice", role_name="reader")
client.grant_privilege_v2(role_name="reader", privilege="Search", collection_name="articles")

Important

The full privilege model, privilege groups, and the built-in roles are an administrator concern. See the Admin Guide RBAC chapter. By default the root user exists with password Milvus and should be secured immediately.


14. The Web UI

Milvus ships a built-in Web UI served on the metrics port (9091) when proxy.http.enableWebUI is enabled (the default). Browse to http://<host>:9091/webui to inspect collections, segments, query-node distribution, slow queries, and component health without writing code.

Tip

For a richer graphical admin experience, the community tool Attu provides a full GUI for managing collections, running searches, and viewing data. It is a separate project, not part of this repository.


15. Troubleshooting

Errors below are taken from the Milvus source error catalog. Format: the message, its cause, and the fix.

Error: collection not loaded

Cause: You searched or queried a collection that has not been loaded into memory. Solution: Call load_collection (or load_partitions) and wait for get_load_state to report loaded, then retry. Prevention: Always load after creating an index and before searching.

Error: shard num (%d) exceeds max configuration (%d)

Cause: You requested more shards than proxy.maxShardNum (default 16) allows at collection creation. Solution: Lower the shard count, or raise proxy.maxShardNum server-side. Prevention: Most collections need only 1–2 shards; add shards only for very high write throughput.

Error: partition number (%d) exceeds max configuration (%d), collection: %s

Cause: The collection (often via a partition key) exceeded rootCoord.maxPartitionNum (default 1024). Solution: Reduce the number of partition-key values, or raise maxPartitionNum. Prevention: Choose a partition key with bounded cardinality.

Error: the specified partitions should be greater than 0 if partition key is used

Cause: A partition-key collection was created with a non-positive partition number. Solution: Specify a positive num_partitions when creating the collection.

Error: collection name [%s] conflicts with an existing alias, please choose a unique name

Cause: You tried to create a collection whose name is already used as an alias. Solution: Pick a different collection name, or drop the conflicting alias first.

Error: create duplicate collection with different parameters, collection: %s

Cause: You re-created an existing collection with a different schema. Solution: Drop the existing collection first, or reuse the identical schema. Prevention: Use has_collection before creating.

Error: PK Field not found

Cause: Your inserted data or query references a primary-key column that the schema does not define, or you omitted the primary key on a non-auto_id collection. Solution: Supply the primary-key field on insert, or set auto_id=True at creation.

Error: dim not found in params

Cause: A vector field was declared without a dim (dimension) parameter. Solution: Add dim=<N> to every dense vector field in the schema.

Error: ttl needs to be a positive integer

Cause: A collection time-to-live property was set to a non-positive value. Solution: Provide a positive integer (seconds) for the TTL property, or omit it.

Error: build index on unsupported data type: %s

Cause: You requested an index type that does not match the field's data type (for example, a dense index on a binary or sparse vector). Solution: Match the index family to the field type — BIN_* for binary, SPARSE_* for sparse, dense indexes for float vectors.

Error: request rejected — quota exceeded / DML denied

Cause: A quota or rate limit fired — memory water mark, disk quota, or an enabled rate limit under quotaAndLimits.*. Solution: Free memory (release collections, scale query nodes), reduce request rate, or raise the relevant quota. Check the server logs for the specific protection that triggered. Prevention: Monitor memory and disk usage; size the cluster for peak load (Admin Guide).

Connection refused / cannot reach 19530

Cause: The server is not up, ports are not published, or a firewall blocks 19530. Solution: Verify curl http://localhost:9091/healthz returns OK, confirm the Compose ports mapping, and check docker compose logs standalone.

Tip

The Web UI (:9091/webui) surfaces slow queries, stuck loads, and unhealthy components and is usually the fastest way to diagnose a misbehaving instance.


16. Frequently Asked Questions

Q: What is the difference between Milvus Lite, Standalone, and a cluster? Milvus Lite is an embedded Python library for prototyping. Standalone is a single-container server for one machine. A cluster runs coordinators and worker nodes separately on Kubernetes for billion-scale, highly available workloads. The client code is identical across all three — only the connection URI changes.

Q: Do I have to create an index before searching? Yes. A collection must have an index on each vector field (or use AUTOINDEX) and must be loaded before search. The lifecycle is create → insert → index → load → search.

Q: Which index and metric should I use? Start with AUTOINDEX. For explicit control, HNSW gives the best QPS/recall on CPU, IVF_FLAT is a simple balanced choice, and DISKANN handles data that does not fit in RAM. Match the metric to your embedding model: COSINE or IP for normalized text embeddings, L2 for many image embeddings, BM25 for full-text.

Q: Can I store more than one vector per entity? Yes — up to proxy.maxVectorFieldNum (default 10) vector fields per collection. Multi-vector collections power hybrid search across modalities.

Q: How fresh are my search results? That depends on the consistency level: Strong (latest), Bounded (default, slight staleness), Session (your own writes), or Eventually (fastest, may lag).

Q: How do I do keyword (full-text) search, not just semantic search? Use a SparseFloatVector field with the BM25 metric and a sparse index, or combine dense + sparse with HybridSearch. Milvus can generate BM25 sparse vectors for you from text fields.

Q: How do I update an entity? Use Upsert with the same primary key, or Delete then Insert. There is no in-place field update for vectors.

Q: Why did my insert succeed but my search return nothing? Either the collection is not loaded, the data was inserted into a partition you are not searching, or your consistency level is Eventually and the write has not yet propagated. Load the collection, check partitions, and try consistency_level="Strong".

Q: What embedding models work with Milvus? Any model that produces fixed-dimension vectors. Milvus integrates with LangChain, LlamaIndex, OpenAI, HuggingFace, and others, and pymilvus[model] provides convenience wrappers. The collection's dimension must equal the model's output dimension.

Q: Is there a GUI? Yes — the built-in Web UI on port 9091 for diagnostics, and the community Attu tool for full graphical administration.

Q: How do I back up my data? Use snapshots (create_snapshot/restore_snapshot) and RBAC backup, or the Milvus Backup tool. See the Admin Guide.

Q: What does milvus run standalone actually start? In standalone mode, one process runs all roles together: the coordinator (MixCoord), Proxy, QueryNode, DataNode, and StreamingNode. This is detailed in the Admin Guide architecture chapter.


17. Where to Go Next

  • Admin Guide — architecture deep dive, the complete milvus.yaml configuration reference, cluster deployment and sizing, security (TLS, RBAC, quotas), monitoring, backup, and upgrades.
  • Official docs — milvus.io/docs for tutorials (RAG, semantic search, recommendation), SDK references, and integration guides.
  • Community — Discord and GitHub Discussions for help; GitHub Issues for bugs.