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 underclient/), 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
dimensionis 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 OpenAItext-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), andmilvus-standalone(the Milvus server itself). All three are defined in the officialdeployments/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
19530serves both the gRPC API and the RESTful API for your clients. Port9091serves the health check (/healthz), Prometheus metrics (/metrics), and the built-in Web UI. The MinIO console is on9001.
Caution
The default credentials baked into a fresh install are username
rootand passwordMilvus. 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 scansetcdand 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 volumespermanently 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
Int64orVarChar. 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=Trueto have Milvus generate primary keys for you on insert. Setenable_dynamic_field=Trueto 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
Upsertrequires 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
flushafter 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/Upsertfor 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 workloadsHNSW(best QPS/recall) orIVF_FLAT(simple, balanced) are safe defaults. For billion-scale data that does not fit in RAM, useDISKANN. UseGPU_CAGRAonly 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.authorizationEnabledset totrue. 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
8.1 Vector similarity search
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
Boundedfor most search traffic,Sessionfor read-after-write within a user session, andStrongonly when you truly need the latest data (it forces a time-tick sync and adds latency).
8.3 Filtered (hybrid scalar + vector) search
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"])
8.5 Range search
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.
8.7 Grouping search
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).
9. Hybrid and Full-Text Search
9.1 Multi-vector hybrid search
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
HybridSearchmethod.
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
compactis throttled byquotaAndLimits.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, andget_restore_snapshot_statecapture and restore a point-in-time view of collection data. - Replication / CDC —
get_replicate_infoandcreate_replicate_streamsupport cross-cluster data replication (Change Data Capture). Thecdcserver 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
rootuser exists with passwordMilvusand 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.yamlconfiguration 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.