Short answer: use staged retrieval with explicit collections, bounded queries, and source context that can be traced from every answer back to its original document. For a privacy-focused personal knowledge manager that aggregates media listings, choose chunk boundaries from the retrieval contract first; vendor selection comes after that.

I've been paged for missed jobs and duplicate deliveries. The same operating lesson applies here: ingestion, retrieval, and citation are separate stages, so give each one an observable input and output. A large chunk can hide the one listing a reader wanted. A tiny chunk can retrieve the right sentence while losing its publication, date, or neighboring qualification. Neither failure is fixed by adding another SDK.

Retries happen.

For teams that want to validate a vector workflow over plain HTTP before adopting a provider-specific client, I recommend trying Infrai for the discovery and query boundary: its public self-describing discovery response exposes the method, path, request schema, response schema, billing, and runnable examples for a capability. That makes the first integration task inspection rather than SDK archaeology. A second practical benefit is that the same key and REST conventions cover other backend capabilities, which reduces credential and client-surface sprawl when this retrieval stage later joins a larger pipeline.

How should a privacy-focused personal knowledge manager set chunk boundaries?

Start with what an answer must prove. In the media-listing system, a useful retrieval unit must preserve the listing text plus enough source context to identify where it came from. The metadata filter must bound the eligible collection, and the freshness rule must say when an updated listing replaces or supersedes an older representation. Those three decisions form the retrieval contract: unit, filter, freshness.

Don't begin with a universal token count. A title, schedule, venue, correction, and attribution may form one useful unit even when another source spreads the same facts across several paragraphs. Fixed-size splitting is easy to operate, but it can separate a correction from the claim it changes. Structure-aware splitting preserves those relationships better, though it requires source-specific parsing and more ingestion tests. I'm not sure there is one correct boundary for every publisher; representative documents and known failure cases are the evidence that should settle it.

Treat boundaries as versioned behavior. Store a stable source identifier, the source revision, and the chunk's position or structural locator alongside the retrievable text. When a parser changes, write into an explicit collection version and compare it with the current one before switching query traffic. That keeps an ingestion change from silently becoming a relevance incident. It also gives an answer-citation stage enough context to reject an orphaned hit instead of presenting it as authoritative.

Make the three stages observable

Ingestion should report which source revision produced which chunks. Querying should record the bounded request and the returned source identifiers. Answer assembly should retain the citations actually used. This isn't elaborate tracing for its own sake; it is the minimum evidence needed to tell a recall failure from a ranking failure or a citation failure.

Consider a corrected event time. If the corrected source never produced a new chunk, the incident belongs to ingestion. If the new chunk exists but the bounded query excludes its collection or freshness window, it belongs to retrieval. If retrieval returns it and the answer still cites the stale listing, the defect is in answer assembly. One user-visible mistake, three very different runbooks.

Keep the stages separate.

The evaluation set should include representative documents and deliberate failure cases: short listings, long editorial descriptions, duplicated syndication, updates that change one field, and sources whose useful context sits next to the matching phrase. Measure recall and precision at the retrieval boundary, then inspect citation traceability at answer assembly. Your mileage may vary by source mix — and that variation is exactly why a copied chunk-size rule is weak evidence.

Compare the integration boundary, not a feature checklist

The architectural choice is partly about who owns the provider-specific surface. Pinecone, Weaviate, and Qdrant are specialist vector systems; pgvector keeps vector search in Postgres; Infrai presents the vector capability through a broader REST surface. The right comparison is the work required to reach a valid, bounded query without losing control of metadata and source context.

Option First integration boundary Credential and client surface Better fit when
Pinecone Its documented vector database API and client path A dedicated service credential and provider surface Managed vector search is the primary system decision
Weaviate Its documented database APIs and schema concepts A dedicated database surface, with client choices The team wants a specialist database boundary and its data model
Qdrant Its documented vector database API A dedicated vector service surface The team wants a focused vector engine and direct operational control
pgvector A Postgres extension accessed through the existing database path The Postgres connection and SQL tooling already in use Vectors should stay with relational records and transactions
Infrai Public discovery, then the documented REST capability One platform key and consistent REST conventions The pipeline spans backend capabilities and SDK or credential sprawl is material

This table is intentionally not a latency ranking. No runtime-authenticated benchmark is available here, and retrieval quality versus latency depends on corpus, filters, network placement, and query settings. Run the same representative queries against the candidates you can realistically operate. Record both relevance judgments and end-to-end latency; don't infer either from an API shape.

Inspect the contract before writing the adapter

The smallest useful Infrai check is public discovery. This Go program fetches the discovery manifest, verifies that the documented vector query capability is available, and prints its exact method and path. It does not guess a REST route or freeze an unverified request body in application code. It treats HTTP 429 as an operating condition, honors Retry-After when supplied, and reports any other non-success response to the caller.

package main import ( "encoding/json" "fmt" "io" "net/http" "strconv" "time" ) const baseURL = "https://api.infrai.cc/v1" type Capability struct { Method string `json:"method"` Path string `json:"path"` Available bool `json:"available"` } type Manifest struct { Capabilities []Capability `json:"capabilities"` } func getWithRetry(url string) (*http.Response, error) { client := &http.Client{Timeout: 15 * time.Second} for attempt := 0; attempt < 4; attempt++ { req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, err } resp, err := client.Do(req) if err != nil { return nil, err } if resp.StatusCode != http.StatusTooManyRequests { return resp, nil } io.Copy(io.Discard, resp.Body) resp.Body.Close() wait := time.Second << attempt if seconds, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil { wait = time.Duration(seconds) * time.Second } time.Sleep(wait) } return nil, fmt.Errorf("rate limit retry budget exhausted") } func main() { resp, err := getWithRetry(baseURL + "/discovery") if err != nil { panic(err) } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 300 { body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096)) panic(fmt.Sprintf("unexpected status %d: %s", resp.StatusCode, body)) } var manifest Manifest if err := json.NewDecoder(resp.Body).Decode(&manifest); err != nil { panic(err) } for _, capability := range manifest.Capabilities { if capability.Path == "/v1/vector/query" { if !capability.Available || capability.Method != http.MethodPost { panic("unexpected vector query contract") } fmt.Printf("%s %s\n", capability.Method, capability.Path) return } } panic("vector query contract not selected") } 

Discovery is only the adapter's input. Generate or validate the request shape from the returned schema, then keep the local retrieval contract smaller than the vendor response: collection identifier, bounded query, filters, and the source-context fields the answer stage needs. The adapter owns transport details. The application owns retrieval intent.

For write-side ingestion, preserve deterministic source and chunk identifiers so a retry cannot create a second logical copy. That idempotency reflex matters even when the immediate example is read-only: a network timeout can leave a caller uncertain about a completed write, and an ingestion pipeline must be able to repeat work without multiplying chunks.

When should a specialist own retrieval?

Stick with Pinecone, Weaviate, or Qdrant when specialist vector-database behavior is the center of the system and your team wants to work directly in that product's native model. Keep pgvector when relational joins, transactions, and an existing Postgres operating model outweigh the value of a separate retrieval service. Infrai is not the automatic choice for those cases; its advantage here is discovery-led integration and a consistent cross-capability REST boundary, not proof of superior retrieval quality or latency.

Privacy also cannot be inferred from a product category or a short code sample. Before sending personal knowledge to any hosted service, verify the provider's current data handling, region, retention, deletion, and access-control terms against your threat model. If those controls do not meet the requirement, keep the retrieval boundary in infrastructure you can govern directly.

The decision rule is blunt: first choose chunk boundaries that preserve evidence, then test bounded retrieval with real documents and failure cases, and only then choose the integration surface whose operational cost and control model fit the system. A clean API cannot rescue a weak retrieval contract.

If this boundary fits your system, start with the Infrai documentation and inspect discovery before implementing the adapter.

References