How Weaviate backups work
A backup module copies the data of the selected collections from every node to an external storage backend. Backups are taken while Weaviate is running. Restoring creates the collections again from that backup on a cluster with a compatible node layout.
| Module | Backend |
|---|---|
backup-s3 | Amazon S3 or S3-compatible storage (MinIO) |
backup-azure | Azure Blob Storage |
backup-gcs | Google Cloud Storage |
backup-filesystem | Local disk; testing only (not usable for multi-node clusters) |
Step 1: enable a module
Docker Compose / environment variables (S3 example):
environment:
ENABLE_MODULES: "backup-s3,text2vec-openai"
BACKUP_S3_BUCKET: "weaviate-backups-prod"
BACKUP_S3_PATH: "cluster-a"
AWS_REGION: "eu-west-1"
# credentials via instance/pod role preferred; or AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
Azure:
ENABLE_MODULES: "backup-azure"
BACKUP_AZURE_CONTAINER: "weaviate-backups"
AZURE_STORAGE_ACCOUNT: "stweaviatebkp"
# AZURE_STORAGE_KEY or AZURE_STORAGE_CONNECTION_STRING, or managed identity support in recent versions
With Helm, set the same through the backups.s3 / backups.azure / backups.gcs sections of the chart values. Check the modules are active:
curl -s http://weaviate:8080/v1/meta | jq '.modules | keys'
Step 2: take a backup
import weaviate
client = weaviate.connect_to_custom(...)
result = client.backup.create(
backup_id="kb-20261028-0200", # lowercase letters, numbers, - and _
backend="s3",
include_collections=["KbChunk", "Faq"], # omit to back up all collections
wait_for_completion=True,
)
print(result.status) # SUCCESS / FAILED
REST equivalent:
curl -X POST http://weaviate:8080/v1/backups/s3 \
-H "Authorization: Bearer $WEAVIATE_ADMIN_KEY" -H "Content-Type: application/json" \
-d '{"id": "kb-20261028-0200", "include": ["KbChunk", "Faq"]}'
curl -s http://weaviate:8080/v1/backups/s3/kb-20261028-0200 -H "Authorization: Bearer $WEAVIATE_ADMIN_KEY" | jq
Status values: STARTED, TRANSFERRING, TRANSFERRED, SUCCESS, FAILED. Only one backup or restore runs at a time per cluster.
Note
Backups include objects, vectors and indexes for the selected collections. Multi-tenant collections are included with their tenants; check your version's notes on how inactive or offloaded tenants are handled before relying on them.
Step 3: restore a collection
A restore fails if a collection with that name already exists. For an accidental delete, the collection is gone, so restore straight back:
result = client.backup.restore(
backup_id="kb-20261028-0200",
backend="s3",
include_collections=["KbChunk"],
wait_for_completion=True,
)
print(result.status)
If the damaged collection still exists (bad data, not a delete), you need it out of the way first. Options:
| Option | Trade-off |
|---|---|
| Delete the damaged collection, then restore | Downtime for that collection; you lose post-backup data unless replayed |
| Restore into a separate Weaviate cluster, verify, then export/import | No downtime, more work |
| Newer versions: restore with a different name, if supported | Check client.backup.restore options in your client version |
Step 4: verify
kb = client.collections.get("KbChunk")
print(kb.aggregate.over_all(total_count=True).total_count)
res = kb.query.near_text(query="how do I reset VPN tokens", limit=3) # or near_vector
for o in res.objects:
print(o.properties["doc_id"])
| Check | Pass |
|---|---|
| Object count | Matches pre-incident count |
| Sample queries | Expected documents returned |
| Schema | Vectorizer, index config and properties as before (kb.config.get()) |
Then replay changes made after the backup from your ingestion system.
Step 5: restore to another cluster (DR)
The target cluster needs:
- The same backup module, pointing at the same bucket/container (replicated to the DR region if needed).
- A compatible number of nodes (restoring a multi-node backup onto a different node count has restrictions; newer versions can map node names with
node_mapping). - The same modules enabled that the collections use (e.g.
text2vec-openai), with valid API keys.
Test this before you need it.
Step 6: schedule and monitor
Kubernetes CronJob calling the REST API:
#!/bin/sh
set -e
ID="nightly-$(date +%Y%m%d-%H%M)"
curl -sf -X POST "$WEAVIATE_URL/v1/backups/s3" -H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" -d "{\"id\":\"$ID\"}"
for i in $(seq 1 360); do
S=$(curl -sf "$WEAVIATE_URL/v1/backups/s3/$ID" -H "Authorization: Bearer $KEY" | jq -r .status)
[ "$S" = "SUCCESS" ] && exit 0
[ "$S" = "FAILED" ] && exit 1
sleep 10
done
exit 1
- Alert when the job fails or no successful backup in 26 hours.
- Expire old backups with bucket lifecycle rules on the backup path.
- Put backups in a different account/subscription than the cluster, with write-once or soft-delete protection against ransomware or mistakes.
Common failures
| Error | Cause |
|---|---|
backup ... already exists | Reused backup ID; make IDs unique |
class ... already exists on restore | Collection still present |
| Access denied / 403 from storage | Module credentials or bucket policy |
another backup/restore in progress | Wait; don't overlap jobs |
| Restore fails on node mismatch | Different node count/names; use node mapping or matching cluster |
Prevent it next time
- Scheduled backups with alerting, retention rules and immutable storage.
- Quarterly restore drill on a separate cluster, timed.
- Keep source documents and an ingestion replay path; backups cover hours, sources cover everything.
- Protect collection deletion with RBAC so only admins can delete collections.