gRPC API
polign_db serves the same operations over gRPC (default
localhost:23001) and HTTP at once — same database, two wire formats. The service
is defined in
proto/vectordb.proto.
The service
service VectorDB { rpc PutVector(PutVectorRequest) returns (PutVectorResponse); rpc PutVectors(PutVectorsRequest) returns (PutVectorsResponse); rpc GetVector(GetVectorRequest) returns (GetVectorResponse); rpc GetVectors(GetVectorsRequest) returns (GetVectorsResponse); rpc ListVectors(ListVectorsRequest) returns (ListVectorsResponse); rpc DeleteVector(DeleteVectorRequest) returns (DeleteVectorResponse); rpc SearchVectors(SearchVectorsRequest) returns (SearchVectorsResponse); // Collection admin — only for servers running the collections registry // (-byo-store); returns Unimplemented otherwise rpc CreateCollection(CreateCollectionRequest) returns (CreateCollectionResponse); rpc GetCollection(GetCollectionRequest) returns (GetCollectionResponse); rpc ListCollections(ListCollectionsRequest) returns (ListCollectionsResponse); rpc DeleteCollection(DeleteCollectionRequest) returns (DeleteCollectionResponse); rpc VerifyCollection(VerifyCollectionRequest) returns (VerifyCollectionResponse); }
For everyday use you only need the first seven: collections are auto-created on the first
PutVector, inferring their dimension from that vector, so most setups never make
an explicit "create collection" call. The five collection-admin RPCs exist for servers that
manage collections on customer-owned buckets (started with -byo-store) — on any
other server they return UNIMPLEMENTED. PutVectors is the batch
upsert: up to 5000 vectors per call, validated as a whole before anything is applied (an
invalid batch writes nothing); chunk larger loads. GetVectors is its read-side
twin — fetch many vectors by id in one call.
Go client (recommended)
For Go services, don't hand-roll stubs — polign_db ships a public client,
github.com/Polign/polign_db/client, that wraps the gRPC API and maps status codes
to sentinel errors so callers never import gRPC types.
import "github.com/Polign/polign_db/client" c, err := client.Dial(ctx, "localhost:23001") // client.WithGRPCDialOptions(...) for TLS defer c.Close() // Store an embedding (collection auto-created from the first vector's dimension) c.Put(ctx, "docs", client.Vector{ ID: "doc-1", Values: embedding, // []float32 from your model Metadata: map[string]string{"title": "Cats"}, }) // Nearest-neighbour search: k=10, ef=0 = server default hits, _ := c.Search(ctx, "docs", queryEmbedding, 10, 0) for _, h := range hits { fmt.Println(h.ID, h.Distance, h.Metadata) } // Typed metadata filters — eq/in/range/exists composed with and/or/not, // built with the client's Filter constructors (no proto types needed) hits, _ = c.Search(ctx, "docs", queryEmbedding, 10, 0, client.SearchOptions{ FilterExpr: client.FilterOr( client.FilterEq("lang", "en"), client.FilterExists("lang", false), ), }) // Also: PutBatch(ctx, coll, []Vector) — batch upsert, up to 5000 per RPC · // Get(ctx, coll, id) · GetBatch(ctx, coll, ids) · List(ctx, coll, limit, offset) · // Delete(ctx, coll, id) if errors.Is(err, client.ErrNotFound) { /* ... */ }
From Python, the Python SDK's
GrpcClient (the [grpc] extra) speaks this same API with stubs
generated from the same proto — identical operations and error mapping as its HTTP client.
Calling it with grpcurl
The server does not register gRPC reflection, so point grpcurl at the proto
file (from a polign_db checkout):
# Put (auto-creates the "docs" collection as 3-dimensional) grpcurl -plaintext -import-path proto -proto vectordb.proto \ -d '{"collection":"docs","vector":{"id":"a","values":[1,0,0],"metadata":{"label":"first"}}}' \ localhost:23001 polign.v1.VectorDB/PutVector # Batch upsert — up to 5000 vectors per call, validated as a whole grpcurl -plaintext -import-path proto -proto vectordb.proto \ -d '{"collection":"docs","vectors":[{"id":"b","values":[0,1,0]},{"id":"c","values":[0,0,1]}]}' \ localhost:23001 polign.v1.VectorDB/PutVectors # Nearest-neighbour search, restricted to matching metadata grpcurl -plaintext -import-path proto -proto vectordb.proto \ -d '{"collection":"docs","values":[0.9,0.1,0],"k":5,"filter":{"label":"first"}}' \ localhost:23001 polign.v1.VectorDB/SearchVectors # Richer predicates via the typed filter_expr tree (eq/in/range/exists + and/or/not) grpcurl -plaintext -import-path proto -proto vectordb.proto \ -d '{"collection":"docs","values":[0.9,0.1,0],"k":5, "filter_expr":{"cond":{"key":"ts","range":{"gte":"2026-01-01"}}}}' \ localhost:23001 polign.v1.VectorDB/SearchVectors # Hybrid search: vector + BM25 text, fused server-side grpcurl -plaintext -import-path proto -proto vectordb.proto \ -d '{"collection":"docs","values":[0.9,0.1,0],"text":"quick brown fox","k":5, "fusion":{"method":"linear","alpha":0.6}}' \ localhost:23001 polign.v1.VectorDB/SearchVectors
Text and hybrid search read the object-store segment index, so they need the server started
with -segment-stores and a persistor running — see the
install & use guide.
SearchVectors options
| Field | What it does |
|---|---|
values | The query embedding. Omit it (and set text) for a pure BM25 search. |
k | How many hits to return. |
ef | Search beam width override; 0 = server default. Larger = more accurate, slower. |
filter | Legacy metadata equality filter, AND across keys — exactly an AND of eq conditions. Applied in-graph on both the in-memory and cold paths. |
filter_expr | Typed filter expression tree: eq/in/range/exists conditions composed with and/or/not. Setting both filter and filter_expr is an error. The Go client builds it with the Filter constructors; the Python client converts its filter dict to it. |
cold | Serve straight from object-storage segments instead of the in-memory index. Requires a segment store. |
nprobe | IVF probe-count override for cold queries; 0 = searcher default. |
text | BM25 query. Alone = text search; together with values = hybrid. |
fusion | Hybrid fusion: method = "rrf" (default, rrf_k=60) or "linear" (alpha = vector-leg weight, default 0.5). Only valid when both legs are present. |
rescore | Accuracy/speed dial for compressed (IVF-PQ) collections: 0 = server default (accuracy-first), > 0 = exact-rescore pool of that size, < 0 = fastest approximate ranking with no exact rescore. Other collection types ignore it. |
Each SearchHit carries a distance (vector metric,
smaller-is-closer) and a score (relevance, larger-is-better: BM25 on a text
search, the fused score on a hybrid one, 0 on a pure vector search).
Errors
| gRPC code | Meaning |
|---|---|
NOT_FOUND | Missing vector or collection on GetVector. |
INVALID_ARGUMENT | Bad request — including a query whose dimension doesn't match the collection's. |
FAILED_PRECONDITION | With placement enabled, this node doesn't own the resource; the message names the owner to redial. |
UNIMPLEMENTED | A collection-admin RPC on a server that isn't running the collections registry (-byo-store). |
UNAUTHENTICATED / PERMISSION_DENIED | Missing or wrong API key on a collection-admin RPC (only those calls require a key). |
RESOURCE_EXHAUSTED | Rate limit hit (servers started with -rate-limit). |
INTERNAL | Anything else. |
Regenerating the stubs
Generated code lives in internal/pb; other languages can generate their own
client from the proto:
protoc --go_out=. --go_opt=module=github.com/Polign/polign_db \
--go-grpc_out=. --go-grpc_opt=module=github.com/Polign/polign_db \
proto/vectordb.proto
This page is the gRPC wire API of polign_db. The same operations are also available over HTTP/JSON — from the command line, or with the curl examples in Install & deploy polign_db.