When you need this
- Accidental delete:
delete_all=Trueon the wrong namespace, or a delete-by-filter that matched too much. - Bad data: a pipeline bug overwrote metadata or vectors with wrong values.
- Before risky operations: re-embedding, metadata migrations, bulk deletes.
A restore creates a new index from the backup; it doesn't roll back the existing one in place. Plan for a host switch in the application.
Step 1: take backups before you need them
On-demand backup before a risky change:
from pinecone import Pinecone
pc = Pinecone(api_key=API_KEY)
backup = pc.create_backup(
index_name="kb-prod",
backup_name="kb-prod-before-reembed-2026-10-28",
description="Before re-embedding with new chunking",
)
print(backup.backup_id, backup.status)
Wait until it's usable:
import time
while pc.describe_backup(backup_id=backup.backup_id).status != "Ready":
time.sleep(10)
List backups:
for b in pc.list_backups(index_name="kb-prod"):
print(b.backup_id, b.name, b.status, b.created_at, b.record_count)
Scheduled backups are available in newer API versions, with one active schedule per index and a required retention period. Set one up for production indexes, and keep on-demand backups for change windows.
Note
Backups cost storage. Delete on-demand backups you no longer need (
pc.delete_backup(backup_id=...)), but only after the change they protected has been verified.
Step 2: also keep the source of truth
A vector backup restores what was in the index. It doesn't help if the bad data was there for a month. Keep these too:
- Source documents (object storage, CMS, database) with versioning.
- Chunk text and metadata in your own store, keyed by record ID.
- Embedding model name and version per record.
With these you can always rebuild the index from scratch, which is the last-resort recovery path.
Step 3: during an incident, stop the damage
- Stop the job or deployment that caused it (pause ingestion, roll back the deploy).
- Note the time the problem started; you need a backup from before it.
- Don't take a new backup and then restore from it; it contains the damage.
Step 4: restore into a new index
pc.create_index_from_backup(
backup_id="<backup_id from before the incident>",
name="kb-prod-restored-20261028",
deletion_protection="enabled",
)
for job in pc.list_restore_jobs():
print(job.restore_job_id, job.status, job.percent_complete)
Poll the job:
job = pc.describe_restore_job(job_id="<restore_job_id>")
print(job.status, job.percent_complete)
The restored index is created in the same cloud and region as the backup by default. Cross-region restore has extra conditions (same cloud provider, matching dimension and metric, transfer charges); check the current documentation before relying on it for DR.
Step 5: verify before switching
restored = pc.Index(host=pc.describe_index("kb-prod-restored-20261028").host)
stats = restored.describe_index_stats()
print(stats.total_vector_count, {k: v.vector_count for k, v in stats.namespaces.items()})
| Check | Pass condition |
|---|---|
| Record count per namespace | Matches the expected count from before the incident |
| Spot fetch | Known IDs return with correct metadata |
| Retrieval quality | Your evaluation question set returns the expected chunks |
| Filters | A few filtered queries return results (metadata intact) |
Step 6: switch the application
Keep the index host in configuration, never hard-coded:
PINECONE_INDEX_HOST=kb-prod-restored-20261028-xxxx.svc.<region>.pinecone.io
Roll the change, watch error rate and retrieval metrics, then:
- Replay writes that happened after the backup was taken (documents changed since then) from your ingestion log or source system's change feed.
- Keep the damaged index for a few days for investigation, with deletion protection on, then delete it.
Step 7: replay the gap
Records written between the backup time and the restore are missing from the restored index. Use your ingestion system:
changed = source.documents_changed_since(backup_created_at)
for doc in changed:
reingest(doc, index=restored)
This is why idempotent ingestion with deterministic IDs matters: replaying is safe.
Recovery options compared
| Scenario | Best option |
|---|---|
| Accidental delete, backup from today | Restore backup, replay the gap |
| Bad data for weeks | Rebuild from source of truth |
| Region outage | Restore a backup in another region (if supported for your setup) or rebuild from source there |
| One namespace damaged | Restore to a new index, then copy that namespace's records back (fetch/upsert by ID list), or switch only that tenant's routing |
Prevent it next time
- Scheduled backups on every production index, with retention that matches your recovery window.
- On-demand backup as a mandatory step in change runbooks for re-embedding and bulk deletes.
- Deletion protection enabled on production indexes.
- A delete helper that refuses an empty namespace and logs every bulk delete.
- A restore drill each quarter, timed end to end.