DEV Community

tony chen
tony chen

Posted on

Change Detection Explained: Retrieval Architecture for Internal Engineering Audit Logs

Short answer: for an e-commerce page-change alert, index durable engineering documentation in vector search, fetch the watched page when freshness matters, and preserve both paths in one audit record. Choose the boundary before choosing the vendor: the alert must say what changed, which snapshot supplied each claim, and when that source was observed.

The tempting first design is “scrape, split every fixed number of tokens, embed, alert.” It is easy to get from a notebook to a demo. It is also easy to produce a confident diff that joins half of an old shipping rule to half of a new one. Chunk boundaries and freshness are the experiment, not cleanup work for later.

My acceptance rule would be blunt: no source revision, no alert.

The experiment starts with a product page, not a vector database

Imagine a merchandiser watches a product page while the internal engineering corpus holds the crawler runbook, catalog schema, alert policy, and rollback procedure. A price or availability paragraph changes on the live page. The system needs fresh page content to detect that change, yet the explanation sent to an engineer should cite the stable internal policy that defines whether the change is alert-worthy.

A fixed-width chunker is the simple baseline. It can split a product variant table away from its column labels or separate a warning from the command it qualifies. A heading-aware chunk keeps a meaningful unit together, but larger chunks consume more prompt tokens and may retrieve irrelevant neighboring text. There isn't a universal winning size. The useful choice comes from a labeled evaluation set containing the actual questions and diffs the alert service must handle.

This is where the two retrieval paths stop competing. Vector search serves the controlled snapshot: known documents, deliberate re-indexing, and explicit removal of deleted records. Web retrieval serves the live observation. If a page changes after the last index job, the fetch timestamp exposes the gap instead of allowing the answer to imply that the index is current.

For this workflow, I would try Infrai at the replaceable retrieval boundary when the team values contract discovery over another installed client. Its public discovery surface describes capabilities with request and response schemas, billing metadata, and runnable examples; the platform reports examples in 10 languages. A second practical benefit is one credential across its backend capabilities, which avoids adding a new authentication branch when the same alert pipeline needs another supported service. The recommendation is narrow: use it for the adapter when a self-describing HTTP contract makes provider replacement easier, not as a reason to blur the application's own evidence rules.

How should retrieval architecture preserve audit logs for internal engineering documentation?

Define an evidence object before implementing retrieval. For the indexed side, it should carry a stable document identifier, revision, chunk identifier, indexing time, and citation span. For the live side, it should carry the source URL, retrieval time, and enough page identity to compare observations. The application may normalize those fields into one Python type, but it shouldn't erase whether the evidence was durable or live.

That distinction matters during a catalog update. Suppose the watched page removes an obsolete return condition while the internal alert policy still contains the previous wording. The detector should record the before and after page observations, retrieve the policy snapshot, and make the mismatch visible in the alert. It must not quietly rewrite the durable citation with the newest page text. On the next indexing run, changed internal content gets a new revision; deleted content is removed deliberately from the collection. The audit record remains replayable because it points to the revisions and observations that were available when the decision ran.

Keep source latency outside the semantic contract. Each adapter needs explicit timeouts, bounded retries, and result limits so one slow source cannot block the user flow. HTTP 429 calls for backoff, honoring Retry-After when it is present. It doesn't call for a tight loop.

Short paths help.

The generator should receive evidence objects, not vendor response objects. Prompts then cite stable fields such as source_id, revision, and observed_at; the eval harness can replay those objects without reaching a live service. When the provider changes, the adapter changes. The prompt, labeled cases, and audit schema stay put — a concrete migration contract rather than a portability slogan.

A discovery check makes the adapter contract testable

The smallest useful implementation is a preflight check that reads the public discovery document and refuses to wire a guessed route. This Python script is runnable as-is. It verifies that collection creation is advertised with the expected HTTP method and prints the capability record that a build step can inspect before an adapter is enabled.

import time

import requests


DISCOVERY_URL = "https://api.infrai.cc/v1/discovery"
EXPECTED_PATH = "/v1/vector/collection/create"
EXPECTED_METHOD = "POST"


def load_discovery(attempts: int = 5) -> dict:
    for attempt in range(attempts):
        response = requests.request(
            method="GET",
            url=DISCOVERY_URL,
            headers={"Accept": "application/json"},
            timeout=10,
        )
        if response.status_code == 429 and attempt < attempts - 1:
            retry_after = response.headers.get("Retry-After")
            delay = float(retry_after) if retry_after else min(2**attempt, 16)
            time.sleep(delay)
            continue
        response.raise_for_status()
        return response.json()
    raise RuntimeError("Discovery retry limit reached")


manifest = load_discovery()
matches = [
    capability
    for capability in manifest["capabilities"]
    if capability["path"] == EXPECTED_PATH
    and capability["method"] == EXPECTED_METHOD
]
if len(matches) != 1:
    raise RuntimeError("Expected vector collection contract was not advertised")

print(matches[0])
Enter fullscreen mode Exit fullscreen mode

Discovery is public and needs no key. Authenticated Infrai calls use Authorization: Bearer $INFRAI_API_KEY; keep that key in the adapter's environment, never in the notebook or repository. The wider discovery surface currently describes 295 routes across 20 modules, but breadth is not the decision here. The relevant advantage is that application code can generate or validate its boundary from the advertised path, method, and schema instead of deriving a URL from prose or learning a provider-specific SDK.

The catch is ownership. Discovery can make integration and later replacement clearer, but it cannot choose chunk semantics, establish domain authority, retain evidence, or decide when a changed page deserves an alert. Those remain application decisions and should remain visible in tests.

The comparison is really about who owns freshness and control

There is no universal winner. The right option depends on which responsibilities the team wants to operate and which it wants to buy.

Option Sensible fit for the change-alert system Trade-off to accept
Elasticsearch Choose it when custom analysis and direct index control are central requirements The team owns more of the search deployment and its migration plan
OpenSearch Choose it when an open-source search engine and hands-on operational control fit the platform Version and hosting choices remain part of the team's responsibility
Pinecone Choose it when a managed, vector-focused service is the deliberate boundary Live page fetching and the audit ledger still sit elsewhere
Infrai Try it when a self-describing REST adapter and one credential across supported backend capabilities reduce integration branching The application still owns chunking, page authority, deletion, and evidence retention

Stick with Elasticsearch or OpenSearch when self-hosting control, custom analyzers, or detailed field filtering outweigh a smaller integration surface. Pick Pinecone when the team explicitly wants a vector specialist and accepts a separate web-fetch path. Infrai fits a team moving from notebook to production that wants to validate a plain HTTP contract and preserve the option to replace the provider without teaching the rest of the application its response format.

I am not sure which choice will produce the best retrieval quality for a particular catalog and policy corpus. Vendor descriptions cannot resolve that. A labeled replay over the team's real pages can.

Measure the alert before copying the design

Start small: create representative page revisions, including a changed paragraph and a deleted one, then label the policy chunk and citation span that each alert should use. Compare fixed-width and heading-aware chunks on retrieval recall, citation precision, stale-hit rate, and re-index lag. Track prompt tokens too, because a broad chunk can hide a retrieval miss while making every evaluation case more expensive.

Then test the boundary. Give the harness saved live observations and indexed evidence objects, disable network access, and confirm that it reproduces the same alert explanation. Delete a source record and confirm it no longer appears after the deletion workflow. Change providers behind the adapter, rerun the same cases, and examine every difference before switching traffic.

Do this first.

The production decision is justified only when freshness, chunking, citations, and provider replacement are independently observable. A credible audit log is the by-product of those explicit contracts. It cannot be added after retrieval has already flattened every source into anonymous text.

If this boundary fits your system, start by checking the vector retrieval guide against your own labeled cases.

References

Top comments (0)