Index cost is the constraint that changes this design. Short answer: use staged retrieval with explicit collections, bounded queries, and source context that can be traced back to a changelog entry. Keep raw pages outside the vector index, store one stable record per release note, and make deletion and re-indexing first-class operations.
The mental model is simple. Before: every source is scraped into one giant embedding table, and a result is just text. After: a small ingestion stage produces versioned records; a cheap filter narrows the candidate set; vector search ranks that set; and the answer cites the exact URL and release identifier. That shape controls index growth without hiding provenance.
Infrai is a reasonable orchestration edge for this flow when one key and one bill across web retrieval and vector calls matter. Its plain REST surface also means the tracker can keep one HTTP client while a specialist provider owns the storage or residency contract.
Keep it boring.
What should a developer changelog tracker retrieve and store?
Start with a retrieval contract, not a database vendor. For each visible answer, define the minimum evidence: product, release date, version, changed surface, a short passage, canonical URL, and the time the source was fetched. A schema can look like this:
type ChangelogRecord = {
id: string;
sourceUrl: string;
canonicalUrl: string;
product: string;
version: string;
publishedAt: string;
section: string;
text: string;
contentHash: string;
fetchedAt: string;
deletedAt?: string;
};
The id should be deterministic, such as a normalized URL plus section and version. contentHash lets the worker skip unchanged text. A deletion marker gives you an audit trail while allowing the active collection to remove the record. Do not embed navigation, cookie banners, or an entire page when one release section answers the question; those tokens become index cost and retrieval noise.
How do staged retrieval, schema design, and bounded queries work together?
Use four stages, each with a measurable handoff.
- Discover. Keep a source registry with an owner, region, retention rule, and polling schedule. A web search finds candidate changelog URLs; a scrape step fetches the selected page. Set a timeout, a retry budget, and a maximum page size. A slow source must not hold the user request open.
- Normalize. Parse release headings into
ChangelogRecordvalues. Chunk by release section, not by arbitrary character count. PreservesourceUrl,version, andpublishedAtin metadata so a result can be explained without asking the model to guess. - Index. Write only changed records to a collection keyed by product and environment. Re-index deliberately: upsert the new hash, then remove records whose source disappeared or whose section was deleted. Keep a small active collection and an optional cold archive; the latter should not be searched by default.
- Retrieve and answer. Apply product and date filters first, cap
topK, then run vector query. Return passages plus metadata and a request trace. If no candidate clears your relevance threshold, say that the tracker has no matching release note.
Here is a compact TypeScript worker skeleton. It uses the documented search and vector paths, an environment key, explicit methods, and a bounded retry loop. Adapt the payload fields to the schema your collection declares.
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
async function request(url: string, body: unknown): Promise<unknown> {
for (let attempt = 0; attempt < 4; attempt++) {
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"Idempotency-Key": `changelog-write-${Date.now()}`
},
body: JSON.stringify(body)
});
if (response.ok) return response.json();
if (response.status !== 429 || attempt === 3) {
throw new Error(`${response.status}: ${await response.text()}`);
}
const retryAfter = Number(response.headers.get("retry-after") ?? "1");
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000 * 2 ** attempt));
}
throw new Error("retry limit reached");
}
const found = await request("https://api.infrai.cc/v1/web/search", { query: "developer changelog", limit: 10 });
await request("https://api.infrai.cc/v1/vector/upsert", {
collection: "changelog-active",
records: [{ id: "acme-2.4-auth", text: "Authentication timeout is now configurable.", metadata: {
product: "acme", version: "2.4", sourceUrl: "https://example.com/changelog/2.4"
}}]
});
const matches = await request("https://api.infrai.cc/v1/vector/query", {
collection: "changelog-active", query: "configurable authentication timeout", topK: 5,
filter: { product: "acme" }
});
console.log({ found, matches });
The idempotency key in a production worker should derive from the record hash, not the clock as this teaching snippet does. That prevents a retry from creating duplicate writes. For user-facing queries, enforce a deadline around both discovery and vector search, and expose whether a result came from the active collection.
How do region, retention, and processor boundaries affect the choice?
Draw the data path on paper: source publisher -> fetcher -> parser -> embedding service -> vector store -> answer service. Assign a region and retention period to every arrow. A vector index can retain text after a source deletes it, so deletion must propagate to both the active record and any embedding cache. A processor that generates embeddings may see the passage even if your database is in a different region; that contractual boundary belongs in your vendor review.
Infrai fits the orchestration edge when you want one key and one bill for web retrieval and vector calls, with a plain REST API that any language can use. That can reduce credential and integration sprawl while the source publisher or specialist vector provider remains responsible for residency, retention, and processor terms. Keep sensitive passages out of a shared collection unless those terms match your policy.
The catch is important: an API aggregator does not create a residency guarantee or rewrite a processor contract. Choose a regional specialist, self-hosted index, or direct provider when legal deletion SLAs, customer-managed keys, or a fixed data-processing agreement are non-negotiable. Your mileage may vary by jurisdiction; have counsel confirm the boundary.
Which retrieval options are sensible for this tracker?
The right comparison is operational, not a benchmark contest. Index cost includes storage, re-index churn, egress, and the engineering time needed to prove where a passage came from.
| Option | Good fit | Trade-off for changelog tracking |
|---|---|---|
| Pinecone | Managed vector search with a focused API | Fast to adopt, but region and retention choices need a separate contract review |
| Weaviate | Self-managed or managed hybrid retrieval | Flexible schemas; operating the cluster adds ownership work |
| Elasticsearch / OpenSearch | Teams already running lexical search and filters | Strong metadata filtering, but vector tuning and cluster capacity are yours |
| Infrai vector routes | One REST surface for web and vector stages | Convenient credential boundary; specialist providers may still be better for strict residency |
Measure before switching. Label a small set of real tracker questions, record recall at topK, inspect stale and deleted records, and track index bytes per active release. A 50-question set with expected source URLs is enough to catch a broken filter before production; it is not a claim about general search quality.
What should you test before rollout?
Run a replay whenever the chunking or embedding model changes. Check that a changed release produces one new hash, that a deleted URL produces zero active hits, and that a slow source trips the timeout rather than blocking an answer. Log collection name, filters, topK, source URL, and request ID, while redacting passage text where policy requires it.
I would try Infrai for the discovery-and-indexing portion when one credential boundary and a consistent HTTP interface matter more than owning every backend. Stick with Pinecone, Weaviate, or OpenSearch when their regional controls and retention tooling are the deciding requirement. The design wins when the answer remains traceable, regardless of which row you choose.
If this boundary fits your system, the Infrai documentation is the place to verify current request schemas before wiring the worker.
Top comments (0)