AI

Qdrant Commands and API Cheat Sheet

This Qdrant cheat sheet is the one-page reference we reach for when running the vector database in real workloads. It covers the commands, REST and gRPC API calls, filter shapes, snapshots, cluster operations, and the configuration env var pattern in one scannable layout. Pin it next to your terminal. For the LLM side of a RAG stack, our Ollama commands cheat sheet is the companion reference.

Original content from computingforgeeks.com - post 167989

Every command below was tested against Qdrant v1.18.x. Where you see ${QDRANT_VERSION} in a script, detect the latest with curl -s https://api.github.com/repos/qdrant/qdrant/releases/latest | jq -r .tag_name. For the full series, start with our Qdrant vector database guide. The official reference lives in the Qdrant documentation.

Ports, defaults, and key URLs

Port / PathPurpose
6333REST API and Web UI
6334gRPC API
6335P2P / raft consensus (cluster only)
/dashboardBuilt in Web UI
/healthzLiveness check
/readyzReadiness check
/metricsPrometheus / OpenMetrics
/sys_metricsSystem level metrics (host CPU, RAM, disk)
/clusterCluster status
/collectionsCollection list
/qdrant/storageDefault storage path inside the container

Run Qdrant with Docker

The fastest way to a working Qdrant. Persistent storage, both ports exposed, container restarts itself.

docker run -d --name qdrant \
  -p 6333:6333 -p 6334:6334 \
  -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
  --restart unless-stopped \
  qdrant/qdrant

With an API key set via env var (recommended for anything reachable beyond localhost):

docker run -d --name qdrant \
  -p 6333:6333 -p 6334:6334 \
  -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
  -e QDRANT__SERVICE__API_KEY="$(openssl rand -base64 32)" \
  --restart unless-stopped \
  qdrant/qdrant

GPU enabled image (Qdrant 1.13+, used by the indexing path):

docker run -d --name qdrant \
  --gpus all \
  -p 6333:6333 -p 6334:6334 \
  -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
  qdrant/qdrant:${QDRANT_VERSION}-gpu-nvidia

Docker Compose snippet

A reusable Compose file with persistent storage, an API key from env, and a memory limit for production:

services:
  qdrant:
    image: qdrant/qdrant:${QDRANT_VERSION}  # https://github.com/qdrant/qdrant/releases
    container_name: qdrant
    restart: unless-stopped
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - ./qdrant_storage:/qdrant/storage:z
      - ./qdrant_snapshots:/qdrant/snapshots:z
    environment:
      QDRANT__SERVICE__API_KEY: ${QDRANT_API_KEY}
    deploy:
      resources:
        limits:
          memory: 4G

Native install one-liners

OSInstall
Ubuntu / Debianwget https://github.com/qdrant/qdrant/releases/download/${QDRANT_VERSION}/qdrant_${QDRANT_VERSION#v}_amd64.deb && sudo apt install ./qdrant_*_amd64.deb
Rocky / RHELUse the Docker or Podman path. Native RPM is not officially published; build from source with cargo if you really need it.
Build from sourcecargo install --git https://github.com/qdrant/qdrant --tag ${QDRANT_VERSION} (requires Rust toolchain and protoc)

systemd service for a native install

Drop this unit file at /etc/qdrant/qdrant.service for a native (non-Docker) install:

# /etc/systemd/system/qdrant.service
[Unit]
Description=Qdrant Vector Database
After=network.target

[Service]
Type=simple
User=qdrant
Group=qdrant
ExecStart=/usr/bin/qdrant --config-path /etc/qdrant/config.yaml
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Create the user, the storage directories, and enable the unit:

sudo useradd -r -s /sbin/nologin qdrant
sudo mkdir -p /var/lib/qdrant/storage /etc/qdrant
sudo chown -R qdrant:qdrant /var/lib/qdrant
sudo systemctl daemon-reload
sudo systemctl enable --now qdrant
sudo systemctl status qdrant

Health and readiness

Three endpoints cover liveness, readiness, and version reporting:

# Liveness
curl -s http://localhost:6333/healthz

# Readiness (returns 200 only when collections are loaded)
curl -s http://localhost:6333/readyz

# Telemetry / version
curl -s http://localhost:6333/telemetry | jq '.app.version'

Collections: create, list, delete

Collections are the top level container. Create, list, inspect, and delete with these calls:

# Create a collection (768-dim, cosine distance)
curl -X PUT http://localhost:6333/collections/articles \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vectors": {
      "size": 768,
      "distance": "Cosine"
    }
  }'

# List
curl -s http://localhost:6333/collections -H "api-key: $QDRANT_API_KEY"

# Get config and stats
curl -s http://localhost:6333/collections/articles -H "api-key: $QDRANT_API_KEY"

# Delete
curl -X DELETE http://localhost:6333/collections/articles -H "api-key: $QDRANT_API_KEY"

Collection with named vectors (dense + sparse for hybrid search):

curl -X PUT http://localhost:6333/collections/articles \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vectors": {
      "dense": {"size": 768, "distance": "Cosine"}
    },
    "sparse_vectors": {
      "bm25": {}
    }
  }'

Points: upsert, get, delete, scroll

Upserts, deletes, scroll, and count all live under the collection's points path:

# Upsert with payload
curl -X PUT http://localhost:6333/collections/articles/points \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "points": [
      {
        "id": 1,
        "vector": [0.1, 0.2, 0.3, "..."],
        "payload": {"title": "Qdrant Guide", "tags": ["ai", "vector"]}
      }
    ]
  }'

# Get by ID
curl -s http://localhost:6333/collections/articles/points/1 -H "api-key: $QDRANT_API_KEY"

# Delete by ID
curl -X POST http://localhost:6333/collections/articles/points/delete \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"points": [1, 2, 3]}'

# Scroll (paginate through all points)
curl -X POST http://localhost:6333/collections/articles/points/scroll \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"limit": 100, "with_payload": true, "with_vector": false}'

# Count
curl -X POST http://localhost:6333/collections/articles/points/count \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"exact": true}'

Search and the modern query API

The legacy /search endpoint still works, but new code should use /query which adds prefetch, hybrid retrieval, and rescoring:

# Basic search
curl -X POST http://localhost:6333/collections/articles/points/search \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vector": [0.1, 0.2, 0.3, "..."],
    "limit": 10,
    "with_payload": true
  }'

# Modern query_points (v1.10+) with prefetch + filter
curl -X POST http://localhost:6333/collections/articles/points/query \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": [0.1, 0.2, 0.3, "..."],
    "limit": 10,
    "filter": {
      "must": [{"key": "tags", "match": {"value": "ai"}}]
    }
  }'

# Recommend (positives and negatives)
curl -X POST http://localhost:6333/collections/articles/points/recommend \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "positive": [1, 5],
    "negative": [99],
    "limit": 10
  }'

Filter syntax cheat card

ClauseExample
match{"key":"category","match":{"value":"books"}}
match any{"key":"tag","match":{"any":["ai","ml"]}}
range{"key":"price","range":{"gte":10,"lt":100}}
geo_bounding_box{"key":"loc","geo_bounding_box":{"top_left":{...},"bottom_right":{...}}}
geo_radius{"key":"loc","geo_radius":{"center":{...},"radius":5000}}
full text{"key":"body","match":{"text":"vector search"}}
is_null{"is_null":{"key":"deleted_at"}}
nested{"key":"meta.tags[]","match":{"value":"ai"}}

Compose with must, should, and must_not. Always pair high cardinality keyword fields with a payload index for fast filtered search.

# Create a payload index (one-time, per field)
curl -X PUT http://localhost:6333/collections/articles/index \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"field_name": "tags", "field_schema": "keyword"}'

Snapshots: create, list, restore

Snapshots are the simplest backup path. The same endpoints handle create, list, download, and restore:

# Create a collection snapshot
curl -X POST http://localhost:6333/collections/articles/snapshots \
  -H "api-key: $QDRANT_API_KEY"

# List
curl -s http://localhost:6333/collections/articles/snapshots -H "api-key: $QDRANT_API_KEY"

# Download
curl -OJ http://localhost:6333/collections/articles/snapshots/<snapshot-name> \
  -H "api-key: $QDRANT_API_KEY"

# Restore from URL
curl -X PUT http://localhost:6333/collections/articles/snapshots/recover \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"location": "http://backups.example.com/articles.snapshot"}'

# Restore from upload (multipart)
curl -X POST http://localhost:6333/collections/articles/snapshots/upload \
  -H "api-key: $QDRANT_API_KEY" \
  -F "[email protected]"

# Full storage snapshot (single node only)
curl -X POST http://localhost:6333/snapshots -H "api-key: $QDRANT_API_KEY"

S3 snapshot backend (since v1.10), configured in config.yaml:

storage:
  snapshots_config:
    snapshots_storage: s3
    s3_config:
      bucket: my-qdrant-snapshots
      region: eu-central-1
      access_key: AKIA...
      secret_key: ...
      endpoint_url: https://s3.eu-central-1.amazonaws.com

Cluster operations

Cluster mode adds raft consensus, sharding, and replication. Enable it in config.yaml:

# Enable cluster mode in config.yaml
cluster:
  enabled: true
  p2p:
    port: 6335
  consensus:
    tick_period_ms: 100

Bootstrap the first node, then join the rest with the --bootstrap flag pointing at any existing peer:

# Bootstrap node 1 (first in the cluster)
qdrant --config-path /etc/qdrant/config.yaml --uri http://node1:6335

# Join nodes 2 and 3
qdrant --config-path /etc/qdrant/config.yaml \
  --bootstrap http://node1:6335 \
  --uri http://node2:6335

# Cluster status
curl -s http://localhost:6333/cluster -H "api-key: $QDRANT_API_KEY"

# Create collection with sharding and replication
curl -X PUT http://localhost:6333/collections/articles \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vectors": {"size": 768, "distance": "Cosine"},
    "shard_number": 6,
    "replication_factor": 2,
    "write_consistency_factor": 1
  }'

# Move a shard between peers
curl -X POST http://localhost:6333/collections/articles/cluster \
  -H "api-key: $QDRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "move_shard": {
      "shard_id": 0,
      "from_peer_id": 1,
      "to_peer_id": 3
    }
  }'

Helm one-liners

The official Helm chart wraps a StatefulSet plus a PVC per pod. Add the repo and install with the right flags for your topology:

helm repo add qdrant https://qdrant.github.io/qdrant-helm
helm repo update

# Single node
helm install qdrant qdrant/qdrant \
  --namespace qdrant --create-namespace \
  --set apiKey=$(openssl rand -base64 32)

# 3 node cluster with persistence
helm install qdrant qdrant/qdrant \
  --namespace qdrant --create-namespace \
  --set replicaCount=3 \
  --set config.cluster.enabled=true \
  --set persistence.size=50Gi \
  --set apiKey=$(openssl rand -base64 32)

# Upgrade
helm upgrade qdrant qdrant/qdrant -n qdrant -f values.yaml

Python client one-page

The qdrant-client Python package mirrors the REST API one-to-one. A working starter:

from qdrant_client import QdrantClient
from qdrant_client.models import (
    Distance, VectorParams, PointStruct,
    Filter, FieldCondition, MatchValue, Range,
)

client = QdrantClient(url="http://localhost:6333", api_key="...")

# Create
client.create_collection(
    collection_name="articles",
    vectors_config=VectorParams(size=768, distance=Distance.COSINE),
)

# Upsert
client.upsert(
    collection_name="articles",
    points=[
        PointStruct(id=1, vector=[0.1] * 768, payload={"title": "Qdrant Guide"}),
    ],
)

# Search with filter
hits = client.query_points(
    collection_name="articles",
    query=[0.1] * 768,
    query_filter=Filter(
        must=[FieldCondition(key="title", match=MatchValue(value="Qdrant Guide"))]
    ),
    limit=10,
    with_payload=True,
).points

# Create payload index
client.create_payload_index(
    collection_name="articles",
    field_name="title",
    field_schema="keyword",
)

# Snapshot
client.create_snapshot(collection_name="articles")

Configuration env var pattern

Every key in config.yaml can be overridden by an environment variable using QDRANT__SECTION__KEY. Two underscores separate levels.

Env varEffect
QDRANT__SERVICE__API_KEYStatic API key for all requests
QDRANT__SERVICE__JWT_RBACEnable JWT based RBAC (also needs API key)
QDRANT__SERVICE__HTTP_PORTREST port (default 6333)
QDRANT__SERVICE__GRPC_PORTgRPC port (default 6334)
QDRANT__SERVICE__ENABLE_TLSBuilt in TLS (with tls.cert + tls.key)
QDRANT__STORAGE__STORAGE_PATHStorage root (default ./storage)
QDRANT__STORAGE__SNAPSHOTS_PATHSnapshots root (default ./snapshots)
QDRANT__LOG_LEVELdebug, info, warn, error
QDRANT__CLUSTER__ENABLEDTurn on cluster mode
QDRANT__TELEMETRY_DISABLEDDisable anonymous telemetry

Web UI URLs

URLWhat it shows
/dashboardMain UI
/dashboard#/welcomeFirst time welcome page
/dashboard#/collectionsCollections list
/dashboard#/consoleBrowser REST runner
/dashboard#/tutorialInteractive tutorial
/dashboard#/datasetsBundled sample datasets

Common gotchas

  • NFS or object storage as the storage backend. Not supported. Qdrant needs block storage with POSIX semantics. Use a PVC backed by a CSI driver that gives you a block volume.
  • Forgetting to set the API key before turning on JWT. The API key is the HMAC secret used to sign and verify JWTs. Set QDRANT__SERVICE__API_KEY first, then enable jwt_rbac.
  • Filtered search without a payload index. The search still works, but it linear scans the filter side. Always create a payload index for high cardinality keyword fields.
  • Binary quantization without rescoring. Default behaviour is good, but if you turned rescoring off, expect a recall drop of 5 to 10 percent. Turn it back on or accept the trade.
  • Restoring an S3 snapshot directly. Qdrant cannot pull from S3 on restore. Download to a local file, then call the /snapshots/upload endpoint.
  • Cluster of size 2. Raft needs more than half the nodes alive to make progress, so a 2 node cluster cannot tolerate a single failure. Run 1, 3, or 5.
  • Default Docker run is open. No auth and no TLS. Fine on a laptop, never on a public host. See our secure Qdrant with API key, TLS, and Nginx article in this series.

Next steps

If you want the full context behind these commands, the pillar Qdrant vector database guide ties everything in this series together. Looking for the equivalent commands for a Postgres-based vector store, our install pgvector walkthrough is the parallel reference.

Related Articles

AI Open Source LLM Comparison Table (2026) AlmaLinux Steps of Installing MariaDB or MySQL on Rocky 9|AlmaLinux 9 DevOps Deploy Static Sites to Cloudflare Pages (Free Hosting) Ansible Terraform and Ansible: Provision Then Configure

Leave a Comment

Press ESC to close