title: Monitoring Vector Databases in Production — Ops Guide
description: Vector database monitoring guide: Milvus/Pinecone/Chroma health checks, query latency tracking, index performance, capacity planning, and alerting. Original ops tutorial.
tags: [ai, vector-db, monitoring, ops]
lang: en
date: 2026-10-23
original: true
faq:
- q: "How to monitor Milvus cluster health?"
a: "Key metrics: ① etcd leader status ② querynode CPU/memory ③ datanode disk usage ④ query latency percentiles. Use the built-in /metrics endpoint and export to Prometheus."
- q: "What causes vector search latency spikes?"
a: "Common causes: ① Index rebuilding during queries ② Disk I/O bottleneck ③ Insufficient querynode replicas ④ Growing dataset without index optimization. Check querynode logs for 'search timeout' warnings."
- q: "How to plan vector DB capacity?"
a: "Rule of thumb: 1M vectors ≈ 4GB storage (for 1024-dim float vectors). Plan for 3x growth over 12 months. Monitor disk usage weekly and set alerts at 70% and 90% thresholds."
- q: "When to switch from ChromaDB to Milvus?"
a: "ChromaDB works well under 10M vectors with single-node deployments. Switch to Milvus when you need horizontal scaling, multi-tenant isolation, or production-grade HA. Also consider Milvus if you need hybrid search capabilities."
- q: "How to back up vector embeddings safely?"
a: "Milvus: use milvus-cli to export collections or snapshot backups. Chroma: copy the persistent directory. Always verify vector counts and dimension consistency after restore."
Monitoring Vector Databases in Production — Ops Guide
Use Case: Monitor and maintain vector databases (Milvus, Pinecone, ChromaDB) that power RAG systems, semantic search, and AI recommendation engines in production.
1. Why Vector DB Monitoring Matters
Vector databases are the backbone of modern AI applications. Unlike traditional relational databases, they have unique failure modes:
- Index corruption: HNSW/IVF indexes can become inconsistent after crashes
- Memory leaks: Query nodes may leak memory during long-running searches
- Silent accuracy degradation: Recall rate drops without explicit errors
- Capacity exhaustion: Vector storage grows linearly with no automatic compaction
A single vector DB outage can take down your entire RAG pipeline.
2. Core Monitoring Metrics
2.1 Milvus Cluster Metrics
| Metric | Type | Alert Threshold |
|---|---|---|
etcd_leader_change_total |
Counter | Any change = investigate |
querynode_cpu_usage |
Gauge | > 80% |
querynode_memory_usage |
Gauge | > 85% |
datanode_disk_usage |
Gauge | > 80% |
proxy_query_latency_seconds |
Histogram | P99 > 1s |
coord_component_health |
Gauge | != 1 |
# Export Milvus metrics to Prometheus
# milvus.yml
metrics_reporter:
enable: true
port: 9091
path: /metrics
2.2 ChromaDB Metrics
ChromaDB is lightweight and has minimal built-in metrics. Monitor via:
import psutil
import shutil
def check_chroma_health(db_path: str) -> dict:
total, used, free = shutil.disk_usage(db_path)
return {
"disk_free_gb": free / (1024**3),
"disk_used_pct": used / total * 100,
"pid_count": len(psutil.pids()),
"timestamp": __import__('datetime').datetime.now().isoformat()
}
2.3 Pinecone Metrics
Pinecone provides a managed dashboard. Key metrics available via API:
# Check index stats
curl -X GET "https://your-index-xxxxx.svc.pinecone.io/describe_index_stats" \
-H "Api-Key: $PINECONE_API_KEY"
3. Query Performance Monitoring
3.1 Latency Breakdown
Vector search latency has three components:
Track each separately:
import time
from prometheus_client import Histogram
search_latency = Histogram(
'vector_search_latency_seconds',
'Vector search latency breakdown',
['component'] # retrieval, embedding, generation
)
def monitored_search(query_vector, top_k=10):
t0 = time.time()
results = collection.query(query_embeddings=[query_vector], n_results=top_k)
retrieval_time = time.time() - t0
search_latency.labels(component='retrieval').observe(retrieval_time)
return results
3.2 Recall Rate Tracking
def evaluate_recall(query, ground_truth_ids, retrieved_ids, k=10):
"""Calculate recall@k"""
relevant = set(ground_truth_ids)
retrieved = set(retrieved_ids[:k])
return len(relevant & retrieved) / len(relevant) if relevant else 0
Set up weekly recall tests with a golden dataset. Alert when recall drops below 0.8.
4. Index Health Checks
4.1 Milvus Index Status
# Check index building status
milvus-cli> show collections
milvus-cli> show entities ops_knowledge
milvus-cli> describe collection ops_knowledge
Watch for:
- IndexState: should be Finished
- PendingIndices: should be 0
- IndexedRows vs TotalRows: should match
4.2 Automatic Index Repair
from pymilvus import utility
def repair_index(collection_name: str):
"""Rebuild index if corrupted"""
state = utility.index_build_progress(collection_name, "embedding")
if state.get("pending_index_num", 0) > 0:
utility.release_collection(collection_name)
utility.create_index(collection_name, "embedding", {
"index_type": "HNSW",
"metric_type": "COSINE",
"params": {"M": 16, "efConstruction": 200}
})
utility.load_collection(collection_name)
5. Capacity Planning
5.1 Storage Estimation Formula
The 1.5 factor accounts for index overhead. For 1024-dim vectors:
| Vectors | Raw Storage | With Index |
|---|---|---|
| 1M | 4 GB | ~6 GB |
| 10M | 40 GB | ~60 GB |
| 100M | 400 GB | ~600 GB |
| 1B | 4 TB | ~6 TB |
5.2 Growth Monitoring
import sqlite3
def track_growth(db_path: str):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM documents")
count = cursor.fetchone()[0]
conn.close()
return count
Log vector count daily and plot growth trends. Set alerts at 70% and 90% capacity.
6. Alerting Rules
6.1 Prometheus Alert Rules
groups:
- name: vector_db_alerts
rules:
- alert: VectorDBHighLatency
expr: histogram_quantile(0.99, rate(vector_search_latency_seconds_bucket[5m])) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "Vector search P99 latency exceeds 1 second"
- alert: VectorDBDiskFull
expr: vector_db_disk_usage_percent > 85
for: 10m
labels:
severity: critical
annotations:
summary: "Vector DB disk usage above 85%"
- alert: VectorDBIndexStuck
expr: vector_db_pending_index_num > 0
for: 30m
labels:
severity: warning
annotations:
summary: "Index building is stuck for {{ $value }} collections"
6.2 Grafana Dashboard JSON
{
"dashboard": {
"title": "Vector Database Monitoring",
"panels": [
{
"title": "Search Latency P99",
"type": "graph",
"targets": [{
"expr": "histogram_quantile(0.99, rate(vector_search_latency_seconds_bucket[5m]))"
}]
},
{
"title": "Vector Count Growth",
"type": "graph",
"targets": [{
"expr": "vector_db_total_vectors"
}]
}
]
}
}
7. Troubleshooting Common Issues
Issue 1: Search queries timing out
Symptoms: Clients receive 504 Gateway Timeout.
排查:
# Check querynode logs
docker logs milvus-querynode --tail 100 | grep -i timeout
# Check system resources
top -p $(pgrep milvus-querynode)
Fix:
- Increase timeout in collection schema
- Add more querynode replicas
- Reduce topK in query requests
Issue 2: Index building taking too long
Symptoms: New vectors inserted but not searchable.
排查:
Fix: - Allocate more resources to datanode - Use IVF_PQ instead of HNSW for faster indexing - Schedule index building during off-peak hours
Issue 3: Memory exhaustion on query nodes
Symptoms: Query nodes OOM and restart cyclically.
排查:
Fix:
- Set memory limits in Docker Compose
- Reduce max_concurrency per querynode
- Upgrade to versions with memory leak fixes
Issue 4: Inconsistent query results
Symptoms: Same query returns different results at different times.
排查: - Check if index rebuilding is in progress - Verify cluster consensus (etcd leader) - Review replica count settings
Fix:
- Wait for index building to complete before querying
- Ensure quorum is reached in etcd
- Set consistency_level to Strong for critical queries
8. Backup and Recovery
8.1 Milvus Backup
# Snapshot backup
milvus-cli> backup collection ops_knowledge --output-path /backup/snapshot-$(date +%Y%m%d)
# Restore
milvus-cli> restore collection ops_knowledge --input-path /backup/snapshot-20261023
8.2 ChromaDB Backup
# Simple directory copy
rsync -av /data/chroma/ /backup/chroma-$(date +%Y%m%d)/
# Verify after restore
sqlite3 /backup/chroma-*/chroma.sqlite3 "SELECT COUNT(*) FROM documents;"
8.3 Recovery Verification Checklist
- Vector count matches original
- Dimensionality is correct
- Sample queries return expected results
- Index state is
Finished - No pending index operations
9. Further Reading
FAQ
milvus-cli to export collections or snapshot backups. Chroma: copy the persistent directory. Always verify vector counts and dimension consistency after restore.