VecParity
Live, quality-verified migration between vector databases.
The Problem
Every team on a managed vector database eventually wants to switch: Pinecone got expensive, you want to self-host, a competitor is faster for your workload. Today that means:
- Copying data over and hoping search quality didn't quietly get worse
- A risky, all-at-once cutover, usually with downtime
- No way to prove, to yourself or a client, that the new database still finds the right things
Existing tools stop at "the data arrived." vector-io/VDF does batch export → import → re-embed across backends, and vendor migration guides (e.g. Qdrant's) only cover moving into their own product. None of them check whether retrieval quality survived the move.
VecParity does two things nothing else does together: migrates incrementally, without downtime, and hands you a parity report (recall@k, result overlap, and score drift between old and new) before you cut over.
Installation
pip install vecparity
With backend support:
pip install "vecparity[pgvector,qdrant,pinecone,milvus,weaviate,chroma]"
pip install "vecparity[all]"
Quick Start
export PGVECTOR_DSN="postgresql://localhost/mydb"
export QDRANT_URL="http://localhost:6333"
# One-shot migration
vecparity migrate --from pgvector://docs --to qdrant://docs
# Live migration: keeps polling for changes until caught up, so your
# app can keep writing to the source the whole time
vecparity migrate --from pgvector://docs --to qdrant://docs --live
# Migrate AND verify retrieval quality survived, gated on a query set
vecparity migrate --from pgvector://docs --to qdrant://docs \
--live --verify-parity --queries golden_queries.json --min-recall 0.95
A failed parity check exits non-zero, so it can wire into CI or a deploy gate to stop a bad migration from silently shipping.
Programmatic use
from vecparity.adapters.pgvector import PgVectorAdapter
from vecparity.adapters.qdrant import QdrantAdapter
from vecparity.sync.engine import SyncEngine
from vecparity.verify.parity import verify_parity
from vecparity.types import QueryCase
source = PgVectorAdapter(conn=pg_conn, table="docs")
target = QdrantAdapter(client=qdrant_client, collection="docs")
SyncEngine(source, target).run_until_caught_up()
report = verify_parity(
source, target,
queries=[QueryCase(query_id="doc-123", top_k=10, label="spot check")],
min_recall_at_k=0.9,
)
print(report.summary())
assert report.passed
What a parity report tells you
For each query, VecParity compares the source's and target's top-k results:
| Metric | Meaning |
|---|---|
recall_at_k |
Fraction of the source's top-k ids also returned by the target |
jaccard_overlap |
Set overlap of the two top-k result lists |
mean_score_drift |
Average similarity-score difference for ids present in both |
ParityReport.passed gates on mean recall@k against a threshold you choose. Use your own golden query set (real user queries plus expected top hits) for a meaningful check, not just random vectors.
Design principles
- Migration-time only, not a permanent ORM. VecParity doesn't try to be a universal query API you build your app against forever; that's how abstractions like this end up leaky. Adapters implement five operations (
get,upsert,delete,list_changed_since,search) and nothing more. - Incremental by default.
list_changed_sinceplus a cursor means re-running a migration only copies what changed, so it's safe to run alongside a live app. - Quality, not just presence. The whole point of this project is the parity report; everything else is plumbing to get there.
Supported backends
| Backend | Status |
|---|---|
| pgvector | ✅ |
| Qdrant | ✅ |
| Pinecone | ✅ |
| Milvus | ✅ |
| Weaviate | ✅ |
| Chroma | ✅ |
| In-memory (testing / reference) | ✅ |
Adding a backend means implementing VectorDBAdapter (vecparity/adapters/base.py); see adapters/memory.py for the smallest possible reference implementation.
Documentation
Full docs, including per-backend connection details and design rationale, live at animeshiology.github.io/vecparity.
Contributing
PRs, issues, and discussions are welcome, especially new backend adapters and real-world golden query sets for testing parity verification against production-shaped data. See CONTRIBUTING.md for dev setup, running tests, and code style.
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vecparity-0.1.0.tar.gz.
File metadata
- Download URL: vecparity-0.1.0.tar.gz
- Upload date:
- Size: 3.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6e4f685c969a5ac5936c6fd6752a9539891e7aa52d3535c064e34007a0bd1d7
|
|
| MD5 |
977d17e88ac7199b443090ac0d5330ff
|
|
| BLAKE2b-256 |
0a96ec952cf6e9c85537d2bfaa12cb1b077c4cd2e4fca540d570cdadf3dc9923
|
Provenance
The following attestation bundles were made for vecparity-0.1.0.tar.gz:
Publisher:
publish.yml on ANIMESHIOLOGY/vecparity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vecparity-0.1.0.tar.gz -
Subject digest:
f6e4f685c969a5ac5936c6fd6752a9539891e7aa52d3535c064e34007a0bd1d7 - Sigstore transparency entry: 2570624705
- Sigstore integration time:
-
Permalink:
ANIMESHIOLOGY/vecparity@5081f3ab12ff09cc7f7a768d14d252a39a62253f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ANIMESHIOLOGY
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5081f3ab12ff09cc7f7a768d14d252a39a62253f -
Trigger Event:
release
-
Statement type:
File details
Details for the file vecparity-0.1.0-py3-none-any.whl.
File metadata
- Download URL: vecparity-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b49d81e8cc03912026d79c06209b0ee586e101f403cd8f444c8e2fcf4d838b6
|
|
| MD5 |
c8668b5d8fb699b70f03335b3765b12e
|
|
| BLAKE2b-256 |
f679ccf598972a2ca0c77592bf15669bdf9b41af22fb6de740e141289b49c986
|
Provenance
The following attestation bundles were made for vecparity-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ANIMESHIOLOGY/vecparity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vecparity-0.1.0-py3-none-any.whl -
Subject digest:
1b49d81e8cc03912026d79c06209b0ee586e101f403cd8f444c8e2fcf4d838b6 - Sigstore transparency entry: 2570624805
- Sigstore integration time:
-
Permalink:
ANIMESHIOLOGY/vecparity@5081f3ab12ff09cc7f7a768d14d252a39a62253f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ANIMESHIOLOGY
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5081f3ab12ff09cc7f7a768d14d252a39a62253f -
Trigger Event:
release
-
Statement type: