Skip to content

embedding_cache: cache key has no model version — silent stale vectors after model update or migration #13

Description

@Yogitmeister

The embedding_cache collection deduplicates embeddings by content hash (visible in mongodb-embedding-retry.ts and the KB import path). The cache key structure does not include a modelId or modelVersion component.

Consequence

If voyage-4-large is updated server-side (Voyage pushes silent model updates occasionally), or if an operator switches the default embedding model via config, the cache silently returns vectors from the old model for any previously-seen content.

A dimension mismatch would be caught at query time. But semantic drift — same output dimensions, different embedding space — will not be caught. ANN results degrade invisibly, and the operator has no signal that recall quality has dropped. This is especially subtle because it only affects content that was seen before the model change; new content gets fresh vectors and appears to work fine.

Suggested fix

Add modelId: string to the cache document schema and include it in the cache key:

// Before
const cacheKey = `hash:${contentHash}`

// After
const cacheKey = `hash:${contentHash}:${modelId}`

This makes the cache naturally namespace-correct across model versions. A one-time migration can backfill existing entries with the then-current model ID (or simply expire them by dropping the collection, since re-embedding is the only safe option anyway).

Alternatively, add a monotonic cacheVersion counter to config that is bumped whenever the embedding model changes. Use it as a cache namespace prefix — stale entries from prior versions are automatically ignored without a migration.


Found this while building a pgvector-based memory layer that uses the same Voyage embedding pipeline. Happy to send a PR if the approach seems right.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions