How to back up a Qdrant vector database
Qdrant backs up through its snapshot API. POST /collections/<name>/snapshots writes a .snapshot archive of one collection while Qdrant keeps serving, and POST /snapshots captures every collection plus aliases on a single node; download each file and keep it off the server. Restore by uploading it to /collections/<name>/snapshots/upload?priority=snapshot, or at startup with --snapshot, into the same minor version or the next one.
What to back up
Qdrant is open source (Apache 2.0); 1.19.1, from September 2026, is current. It has no snapshot schedule or retention of its own; a script does both. The choices:
| Method | Contains | Use it when |
|---|---|---|
| Collection snapshot | One collection's config, points, payloads and indexes on this node; no aliases | Almost always; works on clusters too |
| Full storage snapshot | Every collection plus aliases | A single node you would rebuild whole; restores only at startup |
| Re-embed from source | Nothing stored: you rebuild vectors from the original data | The model changed, or the snapshot can't reach your version |
Snapshots never include the server config, which holds API keys and TLS settings (config.yaml, or QDRANT__ variables in your compose file). Back it up encrypted.
Files land in snapshots_path: /qdrant/snapshots in the Docker image, /var/lib/qdrant/snapshots with the .deb package (/etc/qdrant/config.yaml). Docker examples mount only /qdrant/storage, so add -v /srv/qdrant/snapshots:/qdrant/snapshots. A snapshot is an uncompressed tar, roughly the collection's size on disk, written in storage/snapshots_temp (temp_path changes that) and then moved: a 12 GB collection needs about 12 GB free on each disk.
Keys and permissions
Self-hosted Qdrant accepts anyone who can reach port 6333 until you set service.api_key (or QDRANT__SERVICE__API_KEY), sent in an api-key header; keep the port private or use TLS. Who can do what:
| Action | Admin key | Read-only key | JWT with read-write on the collection |
|---|---|---|---|
| Create or delete a collection snapshot | Yes | No | Yes |
| List or download a collection snapshot | Yes | Yes | Yes |
| Upload or recover a snapshot | Yes | No | No |
| Create a full storage snapshot | Yes | No | No |
The commands below read the URL and admin key from a root-only file (chmod 600); load it with . /etc/qdrant-backup.env:
QDRANT_URL=http://127.0.0.1:6333
QDRANT_API_KEY=your-admin-api-keyTake a collection snapshot
curl -fsS -X POST -H "api-key: $QDRANT_API_KEY" "$QDRANT_URL/collections/products/snapshots?wait=true"The reply's result holds the file name (<collection>-<peer id>-<date-time>.snapshot), its size and a SHA-256 checksum, also written beside it as <name>.checksum. On a large collection, wait=false returns at once and the file appears in the list when done. List, download and delete:
curl -fsS -H "api-key: $QDRANT_API_KEY" "$QDRANT_URL/collections/products/snapshots"curl -fsS -H "api-key: $QDRANT_API_KEY" -o products.snapshot "$QDRANT_URL/collections/products/snapshots/products-5627091348216794-2026-10-04-02-15-00.snapshot"curl -fsS -X DELETE -H "api-key: $QDRANT_API_KEY" "$QDRANT_URL/collections/products/snapshots/products-5627091348216794-2026-10-04-02-15-00.snapshot"Downloading works only over the REST API, not gRPC. A snapshot is a tar archive: tar -tf products.snapshot | head lists it, and comparing sha256sum products.snapshot with the checksum proves the download is complete.
Full storage snapshots and S3
POST /snapshots snapshots every collection and saves the aliases, as full-snapshot-<date-time>.snapshot in snapshots_path. GET /snapshots, GET /snapshots/<name> and DELETE /snapshots/<name> list, download and delete. It is for single nodes only: distributed mode isn't supported, and a full snapshot restores only at startup.
Since 1.10, Qdrant can write snapshots to S3-compatible storage instead of the local disk. Listing, download and recovery work as before:
storage:
snapshots_config:
snapshots_storage: s3
s3_config:
bucket: acme-qdrant-snapshots
region: eu-central-1
access_key: ACCESS_KEY_ID
secret_key: SECRET_ACCESS_KEYFor S3-compatible storage outside AWS, add endpoint_url with the provider's endpoint. The keys can come from QDRANT__STORAGE__SNAPSHOTS_CONFIG__S3_CONFIG__ACCESS_KEY and ..._SECRET_KEY instead. A bucket at another provider gives you the off-site copy in one step (bucket setup); old snapshots still pile up until you delete them.
Run it every night
This script snapshots every collection, downloads and checksums each file, deletes the server's copy, saves the aliases (collection snapshots leave them out) and keeps two days. It needs jq.
#!/bin/bash
set -euo pipefail
. /etc/qdrant-backup.env
DEST=/var/backups/qdrant
H="api-key: $QDRANT_API_KEY"
collections=$(curl -fsS -H "$H" "$QDRANT_URL/collections" | jq -r '.result.collections[].name')
for c in $collections; do
resp=$(curl -fsS -X POST -H "$H" "$QDRANT_URL/collections/$c/snapshots?wait=true")
name=$(echo "$resp" | jq -r '.result.name')
sum=$(echo "$resp" | jq -r '.result.checksum')
mkdir -p "$DEST/$c"
curl -fsS -H "$H" -o "$DEST/$c/$name" "$QDRANT_URL/collections/$c/snapshots/$name"
echo "$sum $DEST/$c/$name" | sha256sum -c --quiet -
curl -fsS -X DELETE -H "$H" "$QDRANT_URL/collections/$c/snapshots/$name" > /dev/null
echo "$(date -Is) $c: $name"
done
curl -fsS -H "$H" "$QDRANT_URL/aliases" > "$DEST/aliases-$(date +%F).json"
find "$DEST" -type f -mtime +1 -deletesudo chmod 700 /usr/local/bin/qdrant-backup.sh15 2 * * * root /usr/local/bin/qdrant-backup.sh >> /var/log/qdrant-backup.log 2>&1Copy /var/backups/qdrant to another provider (3-2-1 rule), see cron schedules for failure alerts, and restore a snapshot on a spare server monthly to time it (testing restores).
Restore a collection
Upload from any machine that reaches the API. The name in the URL is the target, created if missing; restore beside the live collection first:
curl -fsS -X POST -H "api-key: $QDRANT_API_KEY" -F "snapshot=@/var/backups/qdrant/products/products-5627091348216794-2026-10-04-02-15-00.snapshot" "$QDRANT_URL/collections/products_restored/snapshots/upload?priority=snapshot"A file already on the node restores with PUT /collections/<name>/snapshots/recover and a body such as {"location": "file:///qdrant/snapshots/products/products-...snapshot", "priority": "snapshot"}; since 1.17.1 it must sit inside snapshots_path. The location can also be an http(s) URL the node can reach, unless service.enable_snapshot_url_recovery is false. Both endpoints accept a SHA-256 checksum to verify first.
prioritymatters when other replicas of the shard exist:snapshotmakes the file the source of truth,replicakeeps the existing data and resyncs from it,no_syncskips synchronisation. The snapshots page listsreplicaas the default, but the code has defaulted tosnapshotsince 1.9.3. Pass it explicitly.- Re-create aliases from your saved JSON with
POST /collections/aliasesand{"actions": [{"create_alias": {"collection_name": "products", "alias_name": "products-live"}}]}. - Check the result:
POST /collections/products_restored/points/countwith{"exact": true}returns the point count to compare with the original.
On a single node you can also restore at startup. With Docker, run once without publishing the port; when it has started, stop it with Ctrl+C and start your normal container, which finds the collection in the storage volume:
docker run --rm -v /srv/qdrant/storage:/qdrant/storage -v /srv/qdrant/snapshots:/qdrant/snapshots qdrant/qdrant:v1.19.1 ./qdrant --snapshot /qdrant/snapshots/products/products-5627091348216794-2026-10-04-02-15-00.snapshot:products--snapshot <file>:<collection> can repeat; the collection must not exist unless you add --force-snapshot, which replaces it. Never leave either flag in a compose file: with --snapshot alone the next restart stops because the collection exists, and with --force-snapshot every restart overwrites it again. A full storage snapshot restores the same way with --storage-snapshot /qdrant/snapshots/full-snapshot-2026-10-04-02-15-00.snapshot.
Versions and upgrades
A snapshot restores into the same minor version or the next: one from 1.18.1 goes into 1.18.1 or later 1.18 releases, or 1.19.x, not 1.20. Upgrades can't skip minor versions either (1.17 to 1.19 goes through the latest 1.18 patch). Pin the image tag (qdrant/qdrant:v1.19.1, not latest) and snapshot before every upgrade.
To bring an older snapshot forward, restore it into its own version on a spare server and upgrade one minor version at a time. Or copy points between two running instances with Qdrant's migration tool (its qdrant command, with --source.url and --target.url), which reads and writes through the gRPC API on port 6334 rather than copying storage files.
Distributed clusters
- Each node's snapshot holds only that node's shards: create one on every node and keep the files apart by node.
- Restore by uploading each node's file to the same node, with
priority=snapshot. Full storage snapshots and--snapshotare for single nodes only. /collections/<name>/shards/<shard_id>/snapshotssnapshots and restores one shard.- The internal port, 6335, is never protected by the API key; keep it reachable only by other nodes.
When re-embedding is the backup
A snapshot saves vectors you paid to compute. Take 8 million chunks of about 400 tokens: rebuilding means embedding 3.2 billion tokens again, billed per token by an API or bound by your GPU. If your account allows 1 million tokens a minute, that is 3,200 minutes, about 53 hours. The snapshot holds 8,000,000 × 1,536 dimensions × 4 bytes = 49.2 GB of raw float32 vectors, plus payloads and indexes, and restores at disk and network speed.
Re-embedding is the better route when the collection is small (50,000 chunks is 20 million tokens), when the source data is already backed up, as with a PostgreSQL dump, or when the snapshot can't reach your Qdrant version. It is the only route when the embedding model changes or is retired: queries must be embedded by the same model as the stored vectors. Keep the model name and version, vector size, distance and chunking settings in your repository with the code.
Common errors
| Error | Fix |
|---|---|
Must provide an API key or an Authorization bearer token | Add the api-key header. Invalid API key or JWT means the key is wrong. |
Forbidden: Global manage access is required | A read-only key can list and download, not create or restore. Use the admin key. |
Collection products already exists. Use --force-snapshot to overwrite it. | Startup restore into an existing collection. Restore under another name, or add --force-snapshot once. |
Wrong input: Snapshot is not compatible with existing collection: Collection vectors: ... | The target exists with other vector settings or shard count. Restore under a new name. |
Wrong input: Snapshot checksum mismatch: expected ..., got ... | The file is damaged or incomplete. Download it again. |
Forbidden: Snapshot file path must be inside the snapshots directory ... | Move the file under snapshots_path, or upload it instead. |
Forbidden: Snapshot recovery from remote URLs is disabled in the configuration | enable_snapshot_url_recovery is false. Upload the file. |
Frequently asked questions
- Can I back up Qdrant by copying its storage directory?
- Qdrant documents snapshots as the way to back up and move collections, not copies of the storage directory. Use collection snapshots, or a full storage snapshot on a single node.
- Does a Qdrant snapshot include aliases and API keys?
- A collection snapshot includes neither. A full storage snapshot includes aliases. API keys live in the server config, so back that up separately.
- Can I restore a Qdrant snapshot into a newer version?
- Into the same minor version or the next one only, such as 1.18 into 1.19. For bigger jumps, restore into the old version and upgrade one minor version at a time.
- How do I back up a Qdrant cluster?
- Create a collection snapshot on every node, since each holds only its own shards, and restore each file to the same node with priority=snapshot.
How this was checked
Commands, limits and prices were checked against these official pages, on October 4, 2026:
- Qdrant docs: Snapshots (create, list, download, restore, priority, storage, S3)
- Qdrant docs: Backup and restore Qdrant with snapshots (tutorial, multi-node)
- Qdrant docs: Security (API keys, read-only key, table of access)
- Qdrant docs: Configuration (snapshots_path, temp_path, environment variables)
- Qdrant docs: Upgrades (no skipping minor versions)
- Qdrant docs: Installation (Docker volumes)
- Qdrant docs: Distributed deployment
- Qdrant API reference: Snapshots
- Qdrant source, v1.19.1: CLI arguments, snapshot recovery, config.yaml and deb.yaml (flags and messages quoted)
- Qdrant pull request #4265: default snapshot recovery priority switched to snapshot
- Qdrant releases on GitHub
- Qdrant migration tool README (Qdrant to Qdrant)