You upgrade your embedding model. The new one benchmarks better, so you point your pipeline at it, ship it, and within a day retrieval quality falls off a cliff. Or the opposite happens: you change nothing, touch nothing, and over three months your RAG answers slowly get worse for reasons no dashboard explains.
Both of these get filed under the same phrase, "embedding drift," and that is the first mistake. They are two different problems with two different fixes, and treating them as one is why teams reach for the wrong one.
- Model drift is discrete. You change the embedding model, and every vector you already stored is now written in a language the new model cannot read. It is a migration event.
- Distribution drift is continuous. The model stays put, but your data or your users move away from what it was good at, and recall erodes with no error and no alarm.
Most of this post is about the first, because it is the one that quietly turns a one-line config change into a re-indexing of your entire corpus, something many teams discover only when they are mid-migration.
Your embedding model is the schema of your vector store. Changing it is a migration, not a setting.

Model drift is discrete and loud once you know to look. Distribution drift is continuous and silent. Different problems, different fixes.
Why two models cannot share an index
The instinct is that an embedding is just an embedding: a list of floats, similarity is cosine distance, so surely a vector from the new model can be compared against vectors from the old one. It cannot, and the reason is geometric.
When you train two embedding models independently, they do not converge on the same coordinate system. They land in different ones. Research on latent-space alignment (Moschella et al., ICLR 2023) shows that independently trained models produce latent spaces that differ from one another by an unknown, roughly distance-preserving transformation. Inside a single model's space, distances and angles carry meaning. Across two models' spaces they do not, because there is no shared origin, no shared axes, no shared basis. Older work on aligning word-embedding spaces (Conneau et al., ICLR 2018) makes the same point from the other direction: to compare two independently trained spaces at all, you first have to solve for the rotation that maps one onto the other. The alignment is never free.
So when you write model B's query vector and ask it to find neighbors among model A's stored vectors, you are measuring distances between points that live in different rooms. The numbers come back. They are meaningless. And nothing throws an error, which is exactly what makes it dangerous. This is one of the vector database failure modes that only surface in production: the system returns k results, quickly, with a 200, and they are quietly wrong.
The everyday version: it is like re-cataloging a library under a new numbering system but leaving the old shelf numbers printed on the cards. Every lookup still returns a shelf. It just returns the wrong one.

The relative structure is shared across models (cat stays near kitten, far from bicycle); the absolute coordinates are not. A vector from one model is a coordinate on the wrong map.
Model drift is a migration event, not a config change
Once you accept that old and new vectors are incompatible, the consequence is unavoidable: change the model and you must re-embed everything. The vendors say as much through their own constraints.
Google's managed RAG product binds the model to the corpus for its lifetime. In its own words, "the association between your embedding model and the RAG corpus remains fixed for the lifetime of your RAG corpus," and changing it means "you create a new RAG corpus and re-import the data." That is not a quirk of one product. It is the shape of the problem, made explicit by a vendor that had to encode the constraint in its API.
The database schema makes it concrete. In pgvector, a column is typed with a fixed vector dimension, so a new model with a different output dimension is not an edit, it is a new column, which is a schema change. And even when the dimensions happen to match, the vectors are still incompatible for the geometric reason above. Matching dimensions is a trap: it lets the migration "succeed" without an error while returning nonsense.
This is why the framing matters. Your embedding model is the schema of your vector state, and a model swap is a breaking change to that schema. Like any breaking schema change over a large table, it requires a backfill of every record. Distributed systems has a name and a playbook for this, the same discipline you would apply to any versioned, evolving store of state, and you should use it rather than improvise.
The migration architecture
You do not re-embed a production corpus by pointing at the new model and hoping. You run a parallel-change migration: stand the new index up alongside the old, move over while both coexist, then retire the old. Joshua Kerievsky's expand / migrate / contract pattern (written up on Martin Fowler's site as "Parallel Change") maps onto vector re-embedding almost exactly.
| Strategy | How it works | When to use | Cost / risk |
|---|---|---|---|
| Full rebuild | Re-embed the whole corpus offline into a fresh index, swap when done | Small or medium corpus that can tolerate a stale window | Simplest; the index is stale until the swap; you must have kept the original text |
| Blue-green (dual index + alias) | New collection, dual-write new upserts to both, background re-embed the existing points, then flip an alias atomically and drop the old | Production, zero-downtime, want instant rollback | Two indexes during the migration (double storage and compute); deletes must be applied to both |
The blue-green path is where most production systems land, and Weaviate builds it around a collection alias. The alias points at the old collection; you re-embed into the new one in the background; when it is ready you flip the alias in a single atomic operation. Weaviate names the three properties you want from this directly: a "zero-downtime switch," "instant rollback" if the new model underperforms, and "clean architecture" where the old and new models stay fully isolated in separate collections.

Expand, migrate, contract. Stand up the new collection alongside the old, dual-write and backfill in the background, then flip the alias in a single atomic step and retire the old.
Two details bite people. First, you must have stored the original text or source next to each vector, because you cannot re-embed what you did not keep. A vector is not invertible back to its input. Second, deletes and updates that happen during the migration window do not automatically apply to both indexes, so you either pause them or dual-apply them. Otherwise the new index silently diverges from the old while you are building it.
The other drift: when nothing changed but recall did
Model drift is loud once you know to look for it. Distribution drift is the quiet one. You never touched the model, but the documents you are indexing, or the questions your users ask, moved away from what the model handles well, and recall, the share of the genuinely relevant results a search actually returns, degrades a little each week.
Distribution drift is really three things wearing one label. Corpus drift is your indexed documents moving, new topics and new vocabulary the model was never strong on. Query drift is the mirror image: the corpus is stable, but your users start asking different questions. Both are the same statistical shift, the distribution of inputs moving, and both are caught the same way, by watching the vectors' distribution over time. Concept drift is the subtle one, and it is genuinely different: the inputs can look unchanged while the right answer moves underneath them. "The best approach to X" retrieves the wrong thing a year later not because the query changed but because what counts as relevant did. A distribution monitor misses that one entirely, because nothing about the vectors looks different. You catch it only by measuring retrieval quality against what users actually needed.
This is measurable before users complain, just not by your database. Vector-DB dashboards report latency, throughput, and index size, all of which stay green while quality falls, because a system's report of its own health is not the same as its correctness. You have to add a semantic signal. Embedding-monitoring practice (Evidently documents five common methods) treats drift as a shift in the distribution of your vectors between a reference window and a current one: the distance between their centroids, a domain classifier trained to tell old vectors from new, the share of drifted components, and maximum mean discrepancy over rolling windows. Pair that with retrieval quality tracked over time, recall measured against a known-good set, and you catch erosion as a trend rather than an incident.
Know which model made which vector
Both drifts share one prerequisite: you have to know which model produced which vector. In practice it often goes unrecorded, and then a migration becomes archaeology.
The fix is boring and it works. Store the embedding model name and version in each vector's metadata, and name your indexes or collections after the model that fills them. Then a stray vector from the wrong model is detectable instead of invisible, a half-finished migration is auditable, and "which model is this corpus on?" becomes a question you can query rather than guess. This is provenance, the same discipline you would apply to any versioned state: a store that cannot tell you where a value came from cannot tell you whether to trust it.
The takeaway
Treat the embedding model as the schema of your vector store, and the two drifts stop being mysterious.
Model drift is a breaking schema change. Old and new vectors live in different geometric spaces, they cannot be compared, and the only correct response is to re-embed the whole corpus through a parallel-change migration with an alias cutover. Distribution drift is a slow erosion you catch by monitoring the distribution of your vectors and your recall over time, because your database will keep reporting healthy while it happens.
Neither is a tuning problem. Both are state-management problems.
Your embedding model is the schema. Change it like one.
Sources
The vendor behaviors and findings here are reported by the papers and product docs cited, not independently verified. Read them as directional.
- Moschella et al., "Relative representations enable zero-shot latent space communication," ICLR 2023 (arXiv 2209.15430).
- Conneau et al., "Word Translation Without Parallel Data," ICLR 2018 (arXiv 1710.04087).
- Google Vertex AI RAG Engine, "Use embedding models" (product docs).
- Weaviate, "Switching vectorizers" (product docs).
- pgvector README (fixed vector dimension; reindexing).
- Joshua Kerievsky, "Parallel Change"; Fowler and Sadalage, "Evolutionary Database Design".
- Evidently AI, "5 methods to detect drift in ML embeddings".