Peren documentation
Vector indexes
Upsert and query embeddings through a local index or an HTTP, Qdrant, Pinecone, or Weaviate provider.
A vectorize binding stores and queries embeddings through upsert, query, getByIds, and deleteByIds. Worker code keeps one API. The provider chooses where vectors live and which credentials Peren attaches in the node process.
Prerequisites
- A fleet file with
[node],[bucket],[mtls], one service, and one socket - Development certificates from
peren devcert ./certswhen you run locally - For external providers, the process environment variables named by their credential fields
Local index
Write fleet.toml:
[node]
node_id = "00000000-0000-0000-0000-000000000001"
advertise_addr = "127.0.0.1:7000"
listen = "127.0.0.1:7000"
[bucket]
kind = "memory"
[mtls]
ca_cert_path = "./certs/ca.pem"
leaf_cert_path = "./certs/leaf-cert.pem"
leaf_key_path = "./certs/leaf-key.pem"
[[services]]
name = "vector"
worker_bundle_path = "worker.js"
compatibility_date = "2026-01-01"
[services.bindings.VECTORS]
type = "vectorize"
endpoint = "articles"
credential_scope = "vectors"
[services.bindings.VECTORS.provider]
kind = "local"
[[sockets]]
name = "public"
listen = "127.0.0.1:8080"
service = "vector"
type must be vectorize. endpoint names the local index. credential_scope is required. Omitting provider, or setting kind = "local", stores vectors in node-local storage.
Write worker.js:
export default {
async fetch(_request, env) {
await env.VECTORS.upsert([
{ id: "intro", values: [1, 0, 0], metadata: { title: "Intro" } },
{ id: "ops", values: [0, 1, 0], metadata: { title: "Operations" } },
]);
const result = await env.VECTORS.query([1, 0, 0], {
topK: 1,
filter: { title: "Intro" },
returnMetadata: true,
});
return Response.json({
provider: env.VECTORS.provider.kind,
matches: result.matches,
});
},
};
query takes the vector array first and an options object second. It does not take a single { vector } object as its only argument.
Run the node:
peren dev fleet.toml
peren dev binds loopback listeners on port 0 and uses a memory bucket for that session. Call the public: URL it prints. 54321 below stands for that port.
curl -s http://127.0.0.1:54321/
Methods
| Method | Arguments | Result |
|---|---|---|
upsert(vectors) |
array of { id, values, metadata? } |
{ count } |
query(vector, options) |
number array, then { topK?, filter?, returnMetadata?, returnValues?, namespace? } |
{ matches, count } |
getByIds(ids) |
id array | record array |
deleteByIds(ids) |
id array | { count } |
Local query scores with cosine similarity. Dimension mismatches throw TypeError: vector dimensions must match.
Success
The response includes provider: "local" and a matches array. The highest-scoring match for [1, 0, 0] with filter: { title: "Intro" } is intro.
Failure
Local storage failures surface as binding errors on the request. External providers fail when their URL is unreachable or when a required API key environment variable is missing at process start.
HTTP
[services.bindings.VECTORS]
type = "vectorize"
endpoint = "articles"
credential_scope = "vectors"
[services.bindings.VECTORS.provider]
kind = "http"
url = "https://vectors.example"
token_env = "VECTOR_API_TOKEN"
url is required. Optional token_env becomes a Bearer authorization header when set. Peren posts to /upsert, /query, /get, and /delete on that URL.
Qdrant
[services.bindings.VECTORS]
type = "vectorize"
endpoint = "articles"
credential_scope = "vectors"
[services.bindings.VECTORS.provider]
kind = "qdrant"
url = "https://qdrant.example"
collection = "articles"
api_key_env = "QDRANT_API_KEY"
url and collection are required. Optional api_key_env becomes an api-key header when set.
Pinecone
[services.bindings.VECTORS]
type = "vectorize"
endpoint = "articles"
credential_scope = "vectors"
[services.bindings.VECTORS.provider]
kind = "pinecone"
url = "https://articles.svc.pinecone.io"
index = "articles"
namespace = "default"
api_key_env = "PINECONE_API_KEY"
url, index, and api_key_env are required. Optional namespace scopes upsert, query, fetch, and delete. Missing PINECONE_API_KEY fails the process before listeners open.
Weaviate
[services.bindings.VECTORS]
type = "vectorize"
endpoint = "Article"
credential_scope = "vectors"
[services.bindings.VECTORS.provider]
kind = "weaviate"
url = "https://weaviate.example"
class_name = "Article"
api_key_env = "WEAVIATE_API_KEY"
url and class_name are required. Optional api_key_env becomes an Api-Key header when set.