gRPC API

polign_db serves the same operations over gRPC (default localhost:23001) and HTTP at once. Same database, two wire formats. The service definition below is the wire contract; the shipped clients speak it for you.

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, fetching many vectors by id in one call; unlike GetVector, its values come back byte-exact (never a compressed reconstruction).

Typed metadata

Metadata values are typed scalars (server v0.3.0+). The wire carries them in a TypedValue message:

message TypedValue {
  oneof value {
    string str     = 1;
    double number  = 2;
    bool   boolean = 3;
  }
}

Vector.typed_metadata (field 4) and SearchHit.typed_metadata (field 5) are additive: the legacy map<string, string> metadata field is always served with every value's canonical string form, and the typed map is filled only when a record actually holds a non-string value, so pre-0.3.0 clients are untouched. On writes, typed_metadata wins over metadata when both are set. There is no request-side typed opt-in on gRPC (unlike HTTP's ?typed=true); the server always sends both fields, and a client simply reads the one it wants โ€” the Python GrpcClient's typed_metadata=True does exactly that. One round-trip caveat: gRPC carries numbers as doubles, so a source literal like 0.50 reads back as 0.5 (HTTP JSON preserves the literal).

Python client

The Python SDK's GrpcClient (the [grpc] extra) ships pre-generated stubs for this API and maps status codes to the same typed exceptions as its HTTP client. The operations are identical, so you just swap one class:

# pip install "polign[grpc]"
from polign import GrpcClient

client = GrpcClient("localhost:23001")

# Store an embedding (collection auto-created from the first vector's dimension)
client.put("docs", "doc-1", embedding, metadata={"title": "Cats"})

# Nearest-neighbour search; filters, hybrid text search, and batching
# work exactly as in the HTTP client
for hit in client.search("docs", values=query_embedding, k=10):
    print(hit.id, hit.distance, hit.metadata)

Go has a native gRPC client, importable as github.com/Polign/polign_db/client. Other languages can generate stubs from the proto, or talk to the HTTP API: the same operations over JSON, no stubs needed.

SearchVectors options

FieldWhat it does
valuesThe query embedding. Omit it (and set text) for a pure BM25 search.
kHow many hits to return.
efSearch beam width override; 0 = server default. Larger = more accurate, slower.
filterLegacy metadata equality filter, AND across keys, which is exactly an AND of eq conditions. Applied in-graph on both the in-memory and cold paths.
filter_exprTyped filter expression tree: eq/in/range/exists conditions composed with and/or/not. range bounds are strings and compare lexicographically unless the range's numeric flag is set, which parses them as doubles. Setting both filter and filter_expr is an error. The Python client builds it from its filter dict.
coldServe straight from object-storage segments instead of the in-memory index. Requires a segment store.
nprobeIVF probe-count override for cold queries; 0 = searcher default.
textBM25 query. Alone = text search; together with values = hybrid.
fusionHybrid fusion: method = "rrf" (default, rrf_k=60) or "linear" (alpha = vector-leg weight, default 0.5). Only valid when both legs are present.
rescoreAccuracy/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.

ListVectorsRequest takes the same filter_expr to restrict a listing by metadata; offset and the returned total then count matching records only, so a filtered listing pages exactly like an unfiltered one.

Each SearchHit carries a distance (vector metric, smaller-is-closer), a score (relevance, larger-is-better: BM25 on a text search, the fused score on a hybrid one, 0 on a pure vector search), and the hit's metadata (both the string map and, when typed values exist, typed_metadata). 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.

Errors

gRPC codeMeaning
NOT_FOUNDMissing vector or collection on GetVector.
INVALID_ARGUMENTBad request, including a query whose dimension doesn't match the collection's.
FAILED_PRECONDITIONOn data-plane RPCs with placement enabled: this node doesn't own the resource; the message names the owner to redial. On collection-admin RPCs: the collection is still pending verification.
ALREADY_EXISTSCreateCollection on a collection that is already registered.
UNIMPLEMENTEDA collection-admin RPC on a server that isn't running the collections registry (-byo-store), or listing a cold-served resource this node keeps no in-memory index for.
UNAUTHENTICATED / PERMISSION_DENIEDMissing or wrong API key on a collection-admin RPC (only those calls require a key).
RESOURCE_EXHAUSTEDRate limit hit (servers started with -rate-limit), or write backpressure when the unpersisted tail overlay is at its cap.
UNAVAILABLEServer unreachable or connection lost.
INTERNALAnything else.
Which API is this?

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 the HTTP API reference.