RAG freshness is a data-lifecycle contract, not a scheduled re-embedding job. Give every source a stable identity, checksum, version, authorization scope, and lifecycle state. Build new chunks under a new version, activate them atomically, tombstone deletions before asynchronous cleanup, invalidate derived caches, and verify that stale evidence is no longer retrievable.
Deleting the source file alone is not deletion. Copies may remain in parsed artifacts, vectors, keyword indexes, reranker caches, response caches, traces, and evaluation datasets.
Use a source registry as the control plane
Keep an authoritative record outside the vector index:
| Field | Purpose |
|---|---|
source_id | Stable identity across renames and updates |
source_version | Exact version served and cited |
content_checksum | Detects real content change |
scope_id | Tenant and authorization boundary |
source_updated_at | Time reported by the source system |
observed_at | Time the connector saw the version |
activated_at | Time it became eligible for retrieval |
lifecycle_state | Active, superseded, quarantined, tombstoned, deleted |
chunk_manifest | IDs of every derived evidence unit |
deletion_receipt | Completion evidence across stores |
The production RAG architecture places this registry in the knowledge plane. The vector database is a serving index, not the only ledger of truth.
Model updates as version transitions
Do not overwrite chunks one by one while users query the same version. A safer sequence is:
observed → fetched → parsed → validated → indexed → activated↘ quarantinedactive old version → superseded → deleted after retention policy
Build the new version with deterministic chunk IDs such as:
chunk_id = hash(scope_id, source_id, source_version, chunk_locator)
Validate completeness and authorization metadata before activation. Then switch the active version pointer. Queries must filter to lifecycle_state=active and the authorized scope, so partial new versions and superseded chunks cannot leak into results.
If the new version fails validation, keep the last known good version active and alert on freshness lag. Silent partial activation is worse than a visible stale state.
Deletion is a distributed transaction
Use a tombstone-first workflow:
- Authorize and record the deletion request with
scope_idandsource_id. - Mark the source tombstoned in the control plane.
- Make the serving path exclude tombstoned content immediately.
- Enumerate derived artifacts from the chunk manifest.
- Delete vectors, keyword documents, parsed objects, caches, and other governed copies.
- Verify absence using IDs and retrieval probes.
- Store per-system receipts and mark deletion complete.
Tombstoning closes the user-visible access path while eventually consistent stores finish physical deletion. It is not a substitute for deletion where policy requires erasure.
Pinecone documents deletion by record ID, metadata filter, namespace, and index, and notes that data visibility is eventually consistent. Qdrant supports point IDs, payload filters, and explicit delete operations. Those APIs are execution mechanisms; your registry still needs to know exactly which records belong to a source.
Prefer deletion by manifest IDs. Broad metadata filters are useful for recovery but can over-delete if metadata is incomplete or scope is omitted.
Handle every derived copy
Create a deletion coverage matrix:
| Store | Key | Immediate serving block | Physical cleanup | Verification |
|---|---|---|---|---|
| Source connector cache | source ID/version | Tombstone lookup | Delete object | Cache miss |
| Parsed artifacts | source ID/version | Active-version filter | Delete object | Manifest empty |
| Vector index | chunk IDs + scope | Lifecycle/scope filter | Delete points | Fetch absent + query probe |
| Keyword index | chunk IDs + scope | Lifecycle/scope filter | Delete documents | ID lookup absent |
| Reranker/response cache | versioned cache key | Version invalidation | TTL/delete | Old key misses |
| Traces/eval sets | governed record ID | Access restriction | Policy-specific process | Audit receipt |
Do not promise that backups, security logs, or legally retained records are erased through the serving-index job unless they actually are. Document their separate policy and access controls.
Measure freshness as lag, not vibes
Track at least:
observation_lag = observed_at - source_updated_atprocessing_lag = activated_at - observed_atfreshness_age = now - source_updated_at(active_version)deletion_lag = deletion_completed_at - deletion_requested_at
Segment by connector, tenant, source family, and lifecycle state. Alert on the oldest active version and tombstones past their deletion objective, not only average processing time.
The source timestamp may be missing or unreliable. Preserve both source-reported and system-observed times instead of silently treating ingestion time as document time.
Test plan
| Scenario | Required assertion |
|---|---|
| No content change | Checksum prevents unnecessary re-indexing |
| Updated document | Only the new version is retrievable after activation |
| Parser failure | Last good version remains active; alert fires |
| Chunk count drops | Old unmatched chunk IDs are superseded/deleted |
| Rename | Stable source identity prevents duplicate active copies |
| Delete during indexing | Tombstone wins; new version cannot activate |
| Retried delete | Operation is idempotent and receipts remain consistent |
| Cross-tenant ID collision | Scope filter prevents deletion or retrieval outside tenant |
| Cache hit after update | Versioned key misses the old derived result |
| Eventual consistency | Verification retries are bounded before escalation |
Add retrieval cases for questions answerable only by the removed version. A direct ID lookup can be empty while a cached response still cites the deleted text.
Use the RAG failure decision tree when an old answer appears, then measure retrieval and final behavior separately with the RAG evaluation scorecard.
Production checklist
- Stable source identity survives path and title changes.
- New versions activate only after completeness and policy checks.
- Queries require active lifecycle state and authorized scope.
- Tombstones block serving before asynchronous cleanup.
- A manifest enumerates every derived chunk and artifact.
- Cache keys include source/index versions.
- Deletion produces per-system receipts and absence checks.
- Freshness and deletion lag have objectives and owners.
- Update, partial failure, retry, and delete races are tested.
This lifecycle is what makes “current knowledge” an engineering claim rather than marketing copy. JoinAI’s AI Engineer MasterClass covers the production RAG and evaluation practices behind it.




