8. Delete a vector
← Vector exampleswhat this does
DELETE /v1/tenants/:t/vector/:table/:vec_id removes one embedding. It answers 200 in both cases - the body's deleted field carries the outcome, so deleting an id that was never there is a no-op rather than a 404. POST /v1/tenants/:t/vector/:table/delete-bulk is the same operation over a list of ids in a single write.
when to use it
- An erasure request - the row is gone from your source of truth and its embedding has to go with it.
- Re-embedding under a new model: delete the old vectors before writing the new ones, so a stale vector cannot outrank a fresh one.
- Cleaning up after a bad ingest, where you know the ids and want them gone in one call rather than 10,000 requests.
the request
curl -X DELETE "https://$OC_HOST/v1/tenants/$OC_TENANT/vector/shop.products/sku-9281" \
-H "Authorization: Bearer $OC_TOKEN"# Idempotent - an id that was never stored comes back deleted=False, not 404.
result = db.vector.delete("shop.products", "sku-9281")
print(result.deleted)const result = await db.vectorDelete("shop.products", "sku-9281");
console.log(result.deleted);// No typed SDK helper for this route yet - call it directly.
url := fmt.Sprintf("%s/v1/tenants/%s/vector/shop.products/sku-9281", host, tenant)
req, _ := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)what you get back
{
"deleted": true
} deleted is false when nothing was stored under that id. Nothing is written on that path, so a retry costs you a round trip and nothing else.
query parameters
| Field | Required | Notes |
|---|---|---|
| index | no | "hnsw" (default), "ivf" or "ivf_pq". Picks which index family the delete dispatches into. |
| repair | no | HNSW only. true re-links the deleted node's neighbours across the hole instead of leaving a tombstone. Ignored on the IVF and IVF-PQ arms, which shrink their posting lists cleanly. |
deleting in bulk
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/vector/shop.products/delete-bulk" \
-H "Authorization: Bearer $OC_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ids": ["sku-9281", "sku-1144", "sku-5520"],
"index": "hnsw",
"repair": true
}'result = db.vector.delete_bulk(
"shop.products",
ids=["sku-9281", "sku-1144", "sku-5520"],
repair=True,
)
print(result.deleted_count, result.missing_count)// No typed SDK helper for this route yet - call it directly.
const res = await fetch(
`${OC_HOST}/v1/tenants/${OC_TENANT}/vector/shop.products/delete-bulk`,
{
method: "POST",
headers: {
Authorization: `Bearer ${OC_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
ids: ["sku-9281", "sku-1144", "sku-5520"],
repair: true,
}),
},
);
const out = await res.json();
console.log(out.deleted_count, out.missing_count);// No typed SDK helper for this route yet - call it directly.
payload, _ := json.Marshal(map[string]any{
"ids": []string{"sku-9281", "sku-1144", "sku-5520"},
"repair": true,
})
url := fmt.Sprintf("%s/v1/tenants/%s/vector/shop.products/delete-bulk", host, tenant)
req, _ := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)what bulk delete returns
{
"deleted_count": 2,
"missing_count": 1
} The two counts always sum to the number of distinct ids you sent - duplicates inside one call are de-duplicated server-side and count once.
how it works
On the HNSW arm a delete tombstones the node: the graph slot stays, the embedding goes. repair: true additionally re-links the neighbours across the hole, at a higher per-call cost. In bulk that repair runs as a single sweep at the end of the batch rather than once per id.
On the IVF and IVF-PQ arms the id is evicted from its cell's posting list and the payload is deleted; there is no topology to repair. Every successful delete also decrements the tenant's stored-embedding counter, so the quota tracks embeddings currently resident rather than embeddings ever written.
A bulk delete writes one entry to the destructive-operations audit trail carrying the counts, the index family and whether repair ran. The ids themselves are deliberately not logged - a vector id is customer-chosen and routinely a document or user key.
common mistakes
- Treating a missing id as an error. Both routes return 200 for an id that was not there. Assert on
deleted/deleted_count, not on the status code. - Forgetting
indexon an IVF table. The dispatch defaults to HNSW. Delete an IVF row without?index=ivfand the cell posting still lists it. - Sending more than 10,000 ids. That is the per-request cap and it is a 400, not a truncation. Page your own list.
- Expecting
repairto help an IVF delete. It is accepted on both arms so one client shape works everywhere, but it only does anything on HNSW. - Very long ids. A vector id over 1 KiB is refused with 400 - the limit exists so the hash and write path stay bounded.