Indexes and points
This page is the complete data model for VectorDB: what an index is, what a point is, every setting you choose at creation time, and — just as important — which settings can never change afterward.
Index
An index is a named container for vectors. Everything in one index shares two things:
- one fixed width (the number of dimensions in every vector), and
- one distance metric (the rule for measuring how close two vectors are).
Other vector databases call this a "collection" (Qdrant, Pinecone-style products) or an "index" (Vertex AI, Azure AI Search). On this platform, the customer-facing resource is the index; the word collection refers to the internal storage name, explained below.
Names
Index names must match [a-z0-9]([a-z0-9-]*[a-z0-9])? — lowercase letters, digits, and hyphens, starting and ending with a letter or digit, at most 48 characters. Uppercase letters and underscores are refused. Real rejection messages:
{"error":"index name \"My_Index\" must match [a-z0-9]([a-z0-9-]*[a-z0-9])? - lowercase letters, digits and hyphens, starting and ending with an alphanumeric","request_id":"..."}
{"error":"index name \"...\" is longer than 48 characters","request_id":"..."}
The internal collection name
Every read of an index reports a collection field like p_k3xq9m_docs. That is the storage name the platform derived from your project plus your index name, so two projects can both own an index named docs. It is reported so you can recognize your data (for example, through direct engine access); it is never accepted as input anywhere.
Dimensions
dimensions is how many numbers each vector holds. Range 1–65536; omit it (or send 0) and it defaults to 1536, a common embedding-model output size. Every vector you ever write must have exactly this many numbers.
Choose it by looking at your embedding model's documentation — the model's output size is your index's dimensions. Get it wrong and every upsert fails with a dimension-mismatch error (see the quickstart's failure example).
Out-of-range values are rejected at creation:
{"error":"dimensions must be between 1 and 65536, or omit it for the default of 1536","request_id":"..."}
Distance metrics
The distance metric defines "close". It accepts these values, case-insensitively:
| Metric | Aliases | What it measures | When to pick it |
|---|---|---|---|
cosine (default) | — | The angle between vectors, ignoring their length | The usual choice for text embeddings; most embedding models are trained for it |
dot | dotproduct, dot_product | The inner product (direction and length) | When your model's docs say to use dot product / inner product |
euclid | euclidean, l2 | Straight-line distance between the points | When your model's docs say to use Euclidean or L2 distance |
Anything else is rejected:
{"error":"distance must be one of \"cosine\", \"dot\" or \"euclid\"","request_id":"..."}
Advanced creation options
These are for tuning memory and durability trade-offs. The defaults are fine for most workloads; the console keeps them behind an "Advanced options" disclosure for a reason.
| Field | Default | What it does |
|---|---|---|
on_disk | false | Store vectors on disk instead of RAM. Cheaper for big indexes, slower to search. |
payload_on_disk | false | Store payloads on disk instead of RAM. |
quantization.kind | none | Compress vectors to save memory at a small accuracy cost. scalar (alias int8) or binary. |
quantization.quantile | — | Scalar-quantization tuning value, e.g. "0.99". |
quantization.always_ram | false | Keep the compressed copy in RAM even when vectors are on disk. |
shards | 1 | How many pieces the index is split into. |
replicas | 1 | How many copies exist. Range 1–8. |
Invalid quantization kinds are rejected with:
{"error":"quantization.kind must be one of \"none\", \"scalar\" or \"binary\"","request_id":"..."}
Index lifecycle and status
Creating an index returns HTTP 201 immediately with state: "pending" — the storage is built asynchronously. Poll GET .../indexes/{name} until ready: true. Data operations before that return 409 index is not ready yet; its collection has not been created.
| Field | Meaning |
|---|---|
state | Coarse phase: pending, creating, ready, degraded, conflict, or blocked |
ready | The authoritative "you can use it now" boolean |
collection_status | The engine's own health word — green, yellow, red, or grey — present once storage exists |
points_count, vectors_count, segments_count | Live size counters |
message | Human-readable explanation when something is wrong (for example, why a conflict happened) |
What can change, and what can't
Only two fields are editable after creation, via PATCH (project admin role required):
{"replicas": 2, "payload_on_disk": true}
replicas must be 1–8 (replicas must be between 1 and 8 otherwise). Everything else is immutable, and the API tells you why instead of just saying no:
| Field you tried to change | Exact 400 error |
|---|---|
dimensions | dimensions is immutable: existing points cannot be re-embedded, so a different width is a new index, not an edit |
distance | distance is immutable: the metric is baked into the graph built over the existing points |
shards | shards is immutable: resharding moves data and is not performed on a spec edit |
on_disk | on_disk is immutable: vectors are not restaged between memory and disk in place |
quantization | quantization is immutable: it is fixed when the collection is built |
| (empty patch) | no mutable fields to change; the editable fields are replicas and payload_on_disk |
To change dimensions, distance, or any other immutable setting, create a new index and re-ingest your data yourself. The platform does not migrate points between indexes, and deleting an index (HTTP 204) permanently destroys every point in it — there are no snapshots or backups in alpha.
Points
A point is one entry in an index. It has up to three parts:
{"id": 42, "vector": [0.1, 0.2, 0.3, 0.4], "payload": {"tag": "alpha", "source": "manual"}}
Vector (required)
The list of numbers. Its length must equal the index's dimensions exactly. One dense vector per point — VectorDB does not support named or sparse vectors.
Id (optional)
Either an unsigned integer or a UUID string. Nothing else. Omit it and the platform generates a UUID for you. Upserting a point with an existing id overwrites that point — that's the "up" in upsert.
Invalid ids are rejected:
{"error":"point 0: id must be an unsigned integer or a UUID string","request_id":"..."}
{"error":"a string id must be a UUID (or use an unsigned integer)","request_id":"..."}
Payload (optional)
Arbitrary JSON metadata stored with the point. Payloads are what make search useful in practice: at query time you can filter to points whose payload matches a condition (see Search). Store whatever you'll want to filter on or display — tags, source URLs, timestamps, the original text a vector was made from.
Write limits
- At most 1000 points per upsert request (
at most 1000 points per request (got N)), and at least one (points must contain at least one point). - Batches are all-or-nothing: one bad point rejects the whole request; nothing is written.
- Any request body is capped at 32 MiB.
Summary checklist
| Decision | Rule of thumb |
|---|---|
| Name | Lowercase, digits, hyphens; ≤ 48 chars; pick something you can grep for |
| Dimensions | Copy your embedding model's output size; you cannot change it later |
| Distance | cosine unless your model's docs say otherwise; you cannot change it later |
| Ids | Let the platform generate UUIDs unless you need to overwrite points deterministically |
| Payload | Store everything you'll filter on or need to show in results |
| Advanced options | Leave at defaults until memory cost forces the question |
Next: Search covers how to query all of this.