A namespace is a hard partition, not a tag. Changing the embedding model invalidates every vector, so plan the rebuild before you need it.
What a record in a vector store holds
Three parts: an identifier, the vector, and metadata.
The metadata is where most of the design work goes, because it is what you filter and cite by. Pinecone describes these as "extra key-value fields you filter on at query time," with two constraints worth knowing before you load a corpus: the object must be flat, with no nesting, and no null values.
Store the source text alongside the vector. An answer that cites nothing is an answer nobody can check, and going back to your primary database for every retrieved chunk turns one search into a search plus a fan-out of lookups. The duplication costs storage. It buys you a result you can render.
A workable record looks like this:
{
"id": "handbook-2026#chunk-14",
"values": [0.021, -0.118, ...],
"metadata": {
"text": "Refunds are issued to the original payment method...",
"document_id": "handbook-2026",
"section": "Billing",
"updated_at": "2026-08-01",
"tenant_id": "acme"
}
}
The identifier is doing real work there. handbook-2026#chunk-14 is stable
across re-runs, so ingesting the same document twice overwrites rather than
duplicates, and a corrected document replaces its own chunks.
Partitioning with namespaces
Namespaces divide an index. Pinecone documents two uses: multitenancy, one namespace per customer, and faster queries, since a search scans only the relevant records.
The constraint matters more than the feature:
All upserts, queries, and other data read and write operations always target > one namespace.
A namespace is a hard partition, not a tag. Choosing one namespace per tenant is also choosing that you can never search across two tenants in one query. For per-customer isolation that is the point, and it gives you a deletion story that is one call rather than a filtered sweep.
It is the wrong tool when you might want to search across the boundary.
Splitting by document type into policies and handbooks looks tidy until a
question needs both, and then you are issuing two queries and merging ranked
lists from different searches by hand. Use metadata for anything you might want
to combine, and namespaces for boundaries you want enforced.
Why changing the embedding model invalidates everything
A query and a corpus must be embedded by the same model, because vectors from different models sit in different spaces. Comparing across them produces numbers that look like distances and mean nothing.
So there is no incremental migration. You cannot re-embed 10% of your corpus with a new model and serve mixed results, because the new vectors and the old ones are not comparable. The moment you change models, every stored vector is stale.
This catches teams who treat the embedding model as a tuning knob. It is closer to a schema decision.
Re-indexing without downtime
Build beside, then swap.
- Create a second index or namespace, with its own dimension count if the new model differs.
- Re-embed the corpus into it, while the old one keeps serving.
- Compare the two on a fixed set of queries. This is the step people skip, and it is the only evidence that the new model is an improvement.
- Point your application at the new index.
- Keep the old one long enough to roll back, then delete it.
Have your application read the index name from configuration rather than a constant. Step 4 is then a config change, and so is the rollback.
Keep your chunk identifiers stable across the rebuild. When they match, you can diff the two indexes chunk by chunk and see what moved.
Handling updates and deletes
Documents change, and a store you cannot correct becomes a store that confidently serves last quarter's policy.
Derive chunk identifiers from the document and position, as in document_id#n,
so re-ingesting a document overwrites its chunks. Handle shrinkage: if version
two produces 9 chunks where version one produced 12, chunks 10 through 12
survive as orphans unless you delete by document_id first and then write.
For deletions, filter by document_id and remove the matching records. This is
the point of putting document_id in metadata even though no search needs it.
The same applies when a customer leaves. A namespace makes that one call; a metadata filter makes it a query and a delete. Decide which you need while you are designing the record, not when the request arrives.
Further reading
- Pinecone, Indexing overview: record shape, metadata constraints, and namespace behavior.
- Performing similarity search: the read side of everything above.
- Chunking strategies that survive production: what you are storing, and how identifiers let you trace a result back to its source.
Knowledge check
Question 1 of 3
Sign in to save your progress and pick up where you left off.