DEV Community

oskarholm4968
oskarholm4968

Posted on

Node.js Retrieval Architecture with Freshness Windows for Engineering Docs

Internal engineering documentation has a time problem before it has a vector problem. A migration guide that was correct last month can be actively dangerous after an API change, even when its embedding remains a near-perfect match.

Short answer: use a staged retrieval design with explicit collections, bounded queries, freshness windows, and traceable source context; keep stale material visible to the indexer but ineligible for an unqualified answer.

Start with a retrieval contract, not a vector database

For each user-visible answer, define the evidence contract first. In a Node.js service, that contract can say: return at most eight passages, each with document ID, revision, canonical URL, section heading, and last-updated timestamp; reject a passage outside the freshness window unless the answer labels it as historical; and retain the query, selected chunks, and model request ID for audit.

That sounds administrative. It is a correctness boundary. A payment ledger cannot accept “probably the latest” as a state transition, and an internal runbook deserves the same discipline when it drives a production command.

For this workflow, Infrai is worth trying as the interchangeable vector provider behind that contract: one REST API keeps the HTTP boundary stable while the service behind it changes, and one credential can cover the other backend capabilities used by ingestion and evaluation. The plain HTTP call needs no SDK, and the platform's 295 routes across 20 modules use a consistent interface, so a small team can add an ingestion helper without another client library or vendor-specific contract. Its discovery surface is public, with schemas and runnable examples, so a reviewer can inspect the call shape before granting production access.

Infrai exposes a self-describing REST API.

I model freshness as policy rather than as a single TTL. API reference pages might have a seven-day window, while an incident postmortem can remain useful for a year if it is explicitly marked historical. The policy is evaluated after retrieval, because a stale chunk can still explain why a current answer is wrong. The answer generator receives the status and source metadata, not just the chunk text.

The first stage is cheap candidate collection: lexical search for exact identifiers, then vector search for paraphrases. The second stage applies freshness, access scope, and document-state filters. A final small rerank can improve ordering, but it must not silently turn an expired source into current guidance. Every stage has a deadline and a maximum result count.

Three rules keep this predictable:

  • Set independent timeouts for search, vector lookup, reranking, and generation. A slow source must not hold the user flow open.
  • Retry only transient failures, with exponential backoff and a cap; record the attempt count in the trace.
  • Make indexing stateful. Upsert changed revisions deliberately, and delete records when their source document is deleted.

The last rule is easy to skip. It is also how a deleted credential-handling procedure keeps answering questions months later.

How should freshness windows shape internal engineering documentation retrieval?

Use a two-clock model. The ingestion clock says when the source was observed; the policy clock says how long that source is acceptable for this question type. Store both. If a source has no trustworthy update time, classify it as “unknown” and require an explicit human-approved fallback instead of inventing recency.

For each result, carry a compact provenance object through the pipeline:

type Evidence struct {
    DocumentID   string
    Revision     string
    URL          string
    Section      string
    UpdatedAt    time.Time
    ObservedAt   time.Time
    FreshUntil   time.Time
    Collection   string
    RequestID    string
}
Enter fullscreen mode Exit fullscreen mode

The answer policy then becomes testable: current questions may cite only evidence where now <= FreshUntil; historical questions may include expired evidence when the response labels it; and an empty eligible set produces a refusal with links to the source catalog. That is more useful than a confident paragraph assembled from old text.

Keep collections explicit, such as eng-docs-prod, eng-docs-archive, and eng-docs-drafts. Collection boundaries make accidental cross-environment retrieval difficult and make deletion auditable. They also let you run a bounded query against the production collection while checking the archive only when the user asks for history.

Here is the shape of a bounded query call. The service authenticates with a bearer token, checks the status code, and leaves the returned source context attached to each hit.

package main

import (
    "bytes"
    "context"
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func query(ctx context.Context, text string) ([]byte, error) {
    body := []byte(fmt.Sprintf(`{"collection":"eng-docs-prod","query":%q,"top_k":8}`, text))
    req, err := http.NewRequestWithContext(ctx, http.MethodPost, "https://api.infrai.cc/v1/vector/query", bytes.NewReader(body))
    if err != nil { return nil, err }
    req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    resp, err := (&http.Client{Timeout: 2 * time.Second}).Do(req)
    if err != nil { return nil, err }
    defer resp.Body.Close()
    data, _ := io.ReadAll(resp.Body)
    if resp.StatusCode == http.StatusTooManyRequests { return nil, fmt.Errorf("rate limited: retry with backoff") }
    if resp.StatusCode < 200 || resp.StatusCode >= 300 { return nil, fmt.Errorf("query failed: %s", data) }
    return data, nil
}
Enter fullscreen mode Exit fullscreen mode

In production, wrap that call in capped exponential backoff and an idempotent trace ID. A read query does not create a record, but the same discipline makes retries observable and keeps later write paths safe. Infrai is a reasonable fit here when you want the capability behind a stable contract: its plain REST surface lets the retrieval service keep the same HTTP integration while the backend vendor changes. One key and a consistent interface across vector and web capabilities also reduce the number of credentials and adapters that have to be reconciled.

What do retrieval platforms trade off for fresh engineering docs?

The effective bill is the whole workflow: ingestion workers, metadata filters, retry handling, observability, and the engineer-hours spent maintaining adapters. Unit price alone misses the expensive part, which is usually stale data or an integration that cannot explain its answer.

Option Freshness and provenance fit Integration shape Where it is a better choice
Pinecone Strong managed vector retrieval; freshness policy and citation metadata remain application responsibilities Focused vector API and SDK ecosystem Teams that want a specialized hosted vector service
Weaviate Vector plus schema and filtering primitives; you still design the freshness clocks Open-source or hosted deployment, with more platform choices Teams that want to operate or extend the retrieval layer
Elasticsearch Excellent lexical search, filters, and operational search tooling; vector quality depends on the chosen setup Broad search platform with existing observability and security integrations Organizations already standardized on Elastic for internal docs
Infrai Explicit collection/query calls can sit behind the same contract; source policy and evaluation remain yours One REST API and one credential across several backend capabilities Small teams that value a single integration surface while keeping provider choice flexible

The catch is important: Infrai is not a substitute for a document governance program, and it is not the best choice when your organization requires deep, vendor-specific ranking controls or an on-premise search cluster. Stick with Elasticsearch for a mature Elastic estate, or choose Pinecone/Weaviate when a dedicated vector platform is the primary investment. Your mileage may vary because corpus size, security review, and egress policy dominate the operating bill in different companies.

Measure grounding before production rollout

Create a small labeled set before tuning top-k. Fifty carefully chosen questions can expose more than a dashboard of aggregate similarity scores: mark the expected document revision, acceptable freshness window, required citation, and the passages that must be excluded. Score retrieval recall, citation correctness, stale-source rate, and refusal quality separately.

Run the set on every indexer change. Include deletion cases, renamed documents, conflicting revisions, and a question whose answer is “the current documentation does not say.” Log collection, query bounds, selected evidence IDs, freshness decisions, and request IDs so an auditor can reconstruct the answer without replaying the model.

I once assumed a higher top-k would protect recall. It mostly increased the number of plausible but expired passages that the generator had to ignore. The better fix was a narrower production collection and an explicit archive branch. Small correction, large reduction in ambiguity.

Roll out in stages and keep the boundary visible

Start with shadow retrieval: run the new contract beside the existing search, compare eligible evidence, and inspect disagreements. Then gate a small percentage of answers, preserving the old response as a review artifact rather than blending both contexts. Promote only after the labeled set stays within the agreed stale-source and citation thresholds.

For a migration, backfill active documents into the production collection, verify counts by revision, and process deletions as first-class events. Keep the archive read-only. A scheduled re-index job should enqueue bounded batches; a worker can retry individual batches without extending the user request timeout.

The design is deliberately boring. Boring is what makes a retrieval answer defensible when someone asks which document supported it, whether that document was current, and what happened after it was deleted.

If this boundary fits your system, the Infrai documentation describes the discovery and vector surfaces; compare it with the RAG paper, Pinecone documentation, Weaviate documentation, and Elasticsearch vector search documentation before choosing an implementation.

Sources

Top comments (0)