1. Run it
docker run -d --name qdrant --restart unless-stopped \
-p 127.0.0.1:6333:6333 -p 127.0.0.1:6334:6334 \
-v /srv/qdrant/storage:/qdrant/storage \
-v /srv/qdrant/snapshots:/qdrant/snapshots \
-v /srv/qdrant/config.yaml:/qdrant/config/production.yaml \
-v /srv/qdrant/tls:/qdrant/tls:ro \
-e QDRANT__SERVICE__API_KEY="$QDRANT_API_KEY" \
-e QDRANT__SERVICE__READ_ONLY_API_KEY="$QDRANT_RO_KEY" \
qdrant/qdrant:v1.13.0
Pin a version, and keep storage on a fast SSD volume. The API keys come from environment variables so they stay out of the config file.
# config.yaml
service:
enable_tls: true
tls:
cert: /qdrant/tls/cert.pem
key: /qdrant/tls/key.pem
storage:
storage_path: /qdrant/storage
snapshots_path: /qdrant/snapshots
Never expose Qdrant without an API key. Open instances get found and emptied.
2. Create a collection
curl -X PUT "https://qdrant01:6333/collections/kb_docs" \
-H "api-key: $QDRANT_API_KEY" -H "Content-Type: application/json" -d '{
"vectors": { "size": 1536, "distance": "Cosine", "on_disk": true },
"hnsw_config": { "m": 16, "ef_construct": 200 },
"quantization_config": { "scalar": { "type": "int8", "quantile": 0.99, "always_ram": true } },
"optimizers_config": { "default_segment_number": 4 }
}'
sizemust match your embedding model (1536 fortext-embedding-3-small, 3072 for-large, and so on).- Scalar quantisation with
always_ramkeeps compact int8 vectors in memory and the originals on disk, for about 4× less RAM with a small recall cost (use rescoring to recover most of it).
3. Payload indexes for filters
curl -X PUT "https://qdrant01:6333/collections/kb_docs/index" -H "api-key: $QDRANT_API_KEY" \
-H "Content-Type: application/json" -d '{"field_name": "tenant_id", "field_schema": "keyword"}'
Index every field you filter on (tenant, document type, ACL group, date). Filters on unindexed fields slow searches down a lot.
4. Memory sizing (rough)
RAM ≈ vectors × dimensions × bytes per value × 1.5 (overhead)
1M × 1536 × 4 bytes (float32) × 1.5 ≈ 9.2 GB
with int8 quantisation in RAM and originals on disk ≈ 2.3 GB + page cache
5. Search with rescoring
POST /collections/kb_docs/points/query
{
"query": [0.01, 0.02, ...],
"filter": { "must": [ { "key": "tenant_id", "match": { "value": "acme" } } ] },
"params": { "hnsw_ef": 128, "quantization": { "rescore": true, "oversampling": 2.0 } },
"limit": 10,
"with_payload": true
}
6. Snapshots (backups)
curl -X POST "https://qdrant01:6333/collections/kb_docs/snapshots" -H "api-key: $QDRANT_API_KEY"
curl "https://qdrant01:6333/collections/kb_docs/snapshots" -H "api-key: $QDRANT_API_KEY"
Copy snapshot files from /srv/qdrant/snapshots to object storage on a schedule. To restore: PUT /collections/kb_docs/snapshots/recover with the snapshot location.
7. Monitoring
/metrics(Prometheus): request latency, collection sizes, and errors./collections/kb_docs: status should begreen.yellowmeans optimising,redmeans an error.- Alert on disk usage, memory, and p95 search latency.
8. Limits of standalone
One node means downtime for restarts and upgrades, and no replication. Add a cluster with replication factor ≥ 2 when search is on a critical path (see the vector database HA post).
Tip
Keep the source documents and chunk text in your own store as well. You can always rebuild a vector index from source; you can't rebuild source from the index.