VectorDB guide
This is the end-to-end walkthrough for VectorDB, the platform's managed vector-search service. It assumes only an account and a project, and it takes you from zero to a queryable index.
What VectorDB is
VectorDB stores embeddings — the long numeric vectors produced by an embedding model — and answers "which stored vectors are closest to this query vector?" in milliseconds. Use it for semantic search, retrieval-augmented generation (RAG), agent long-term memory, recommendations, and deduplication.
Use cases:
- Semantic search over docs, tickets, or products.
- RAG — fetch the most relevant passages from your own data to ground a language model's answer.
- Agent long-term memory — the agent memory bank is built on top.
- Near-duplicate detection — "have we answered a question like this before?"
You bring the vectors. VectorDB stores, indexes, and serves them; it does not run an embedding model for you.
Quick start: searchable index in five commands
# 1. sign in once
platformctl login
# 2. create a small demo index (4 dimensions, cosine distance)
platformctl vectordb create docs --dimensions 4 --distance cosine
# 3. insert two points
printf '%s' '{"points":[{"id":1,"vector":[1,0,0,0],"payload":{"tag":"alpha"}},
{"id":2,"vector":[0,1,0,0],"payload":{"tag":"beta"}}]}' \
| platformctl vectordb upsert docs --points -
# 4. query for vectors near [1,0,0,0], top 2
platformctl vectordb query docs --vector '[1,0,0,0]' --top-k 2
# 5. clean up when done
platformctl vectordb delete docs
The same flow in the Console is Data services → VectorDB → Create index, then the index's Query section. Step 3 has no console equivalent: the console does not write points, by design — see the walkthrough below.
Core concepts
- An index is the named container. Every vector in it has the same width (dimension count) and distance rule.
- Dimensions (width) are fixed at create time and must match every vector you write. Leave it unset and you get the width of the platform's own hosted embedding model, so an index fed by our
/embeddingsendpoint fits with nothing set. Set it explicitly only when you bring vectors from a different model. See Inference. - Distance is the similarity function:
cosine,dot, oreuclid. Pick once at create time. - A point is one vector, plus an optional id — an unsigned integer or a UUID string, nothing else — and an optional JSON payload, the metadata the filter language can see. Omit the id and the platform generates a UUID.
- A query returns the top-k nearest points, each with a similarity score.
top_kis per-request. - A filter narrows a query by payload fields — for example
tag = 'alpha'. It is not a full query language. - The index is scoped to your project and invisible to other projects. Two projects can both have an index named
docs. - Index state moves
pending→ready→ (degradedon failure).readyis the only state that accepts queries. - Vector writes are idempotent on id: re-inserting the same id replaces the vector and payload.
- A query against an unreadied index returns an error; poll
getuntilready: true.
API examples
export VDB="https://api.codyhill.dev"
export PROJ="$(platformctl projects list -o json | jq -r '.[0].id')"
export TOK="<session token or API key>"
Create an index (platform default width, cosine):
curl -sX POST "$VDB/v1/projects/$PROJ/indexes" \
-H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"name":"docs","distance":"cosine"}'
Upsert points:
curl -sX POST "$VDB/v1/projects/$PROJ/indexes/docs:upsert" \
-H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"points":[{"id":1,"vector":[...],"payload":{"tag":"handbook"}}]}'
Note the :verb suffix. Writing and searching are custom methods — a literal :verb on the end of the index path, always with POST. There is no path-segment or query-parameter form; /indexes/docs/upsert matches no route and comes back 404.
Query top-5 with a payload filter:
curl -sX POST "$VDB/v1/projects/$PROJ/indexes/docs:query" \
-H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"vector":[...],"top_k":5,"filter":{"must":[{"key":"tag","match":{"value":"handbook"}}]}}'
CLI examples
platformctl vectordb list # all indexes in the project
platformctl vectordb get docs # state, dimension, distance, point count
platformctl vectordb create docs --distance cosine
platformctl vectordb upsert docs --points @points.json # accepts literal, @file, or - for stdin
platformctl vectordb query docs --vector @vec.json --top-k 10
platformctl vectordb delete-points docs --ids 1,2 # remove specific points
platformctl vectordb delete docs # drop the index
Console walkthrough
- Open the Console, pick your project.
- Go to Data services → VectorDB.
- Click Create index. Set Dimensions to match your embedding model and Distance to
cosineunless you have a reason not to. - When the new index flips to Ready, open it.
- The Data section browses the points already in the index — id and payload, a page at a time — and each row can be deleted. The Query section takes a vector and a Top K and shows results with scores; Fill with a random vector smoke-tests that the index answers at all. The console deliberately does not insert points: embeddings belong in your code, not a textarea. Use
platformctl vectordb upsertor the API. - The Payload filter field in the Query section accepts the same JSON filter language as the API.
- Delete index permanently drops the index and all points.
Limits and quotas
The VectorDB service enforces these at the API:
| Limit | Default |
|---|---|
| Max points per upsert request | 1000 |
| Max request body size | 32 MiB |
Max top_k per query | 1000 |
| Max dimension count | bound by your embedding model; request body cap is the effective ceiling |
If you hit a body-size error, split a bulk upsert into batches of 1000 points or fewer.
There is no enforced ceiling on indexes per project. Each index is a separate collection with its own memory footprint, so many small indexes cost more than one large one. One related bound does exist: a direct-access credential enumerates at most 256 collections per token and reports truncated: true beyond that.
Troubleshooting snippets
| Symptom | First thing to check |
|---|---|
| Query returns "index not ready" | platformctl vectordb get docs — poll until state: ready and ready: true. |
| Upsert returns "vector dimension mismatch" | One of your vectors is not the index's declared width. Every point in one index must be the same width. |
| Empty result set on an obvious match | Your query vector is in a different dimension space than the indexed vectors — same model, or the numbers will not be comparable. |
| Filter matches nothing | The payload key is case-sensitive and must match exactly; Tag and tag are different keys. |
| Error "top_k exceeds maximum" | Lower --top-k to 1000 or fewer. |
| Bulk upsert is slow | Split into 1000-point batches. Run batches in parallel from the client; the service is built to absorb concurrent writes. |
| Delete worked but storage still shows in usage | Deletion is asynchronous; the underlying collection drains within a few minutes. |
Security notes
- Indexes are project-scoped by construction. The API takes a project id on every call, and the service resolves that to the storage collection behind the index. No cross-project index is possible.
- Bearer tokens gate both data and control plane. The same credential that creates an index is the one that upserts and queries. Rotate it like any other credential.
- Direct-access credentials —
GET /v1/projects/<id>/vectordb/credentials, project admin only — returns the low-level connection details for a client that would rather address the index storage directly than go through this REST API:service_url(a private address, reachable only from workloads in your project),collection_prefix, the exactcollectionscovered, and — only when the platform has per-project JWT enforcement turned on — a time-limitedtokenscoped read-write to those collections. Because it is read-write over every index in the project, it belongs in trusted server-side code, never in a browser. It is also a snapshot: an index created after the token was minted is not covered until you fetch credentials again. An address reachable from outside the platform (external_service_url) appears only when a token was issued and your project has published its vector database as an endpoint; otherwise the field is absent. - Payload content is your responsibility. VectorDB does not classify, redact, or audit JSON payloads — do not embed Personally Identifiable Information unless you have a policy reason to.
- Query results are not logged by the service, but they are returned over TLS and can be captured anywhere your client runs. Treat the query log in your own application with the same care as the data itself.
Where next
- Collections and points — bulk writes, point addressing, and payload filters.
- Search — the full query language, filters, and scoring.
- Use with agents — how VectorDB powers agent long-term memory.