This is the multi-page printable view of this section. .
Release Notes
- 1: VectorChord 1.1: Native 4/8 Bit Vector Types and Per-Index Query Defaults
- 2: VectorChord 1.0: Developer-First Vector Search on Postgres, 100x Faster Indexing than pgvector
- 3: VectorChord 0.5: New RaBitQ-empowered DiskANN Index and Continuous Recall Measurement
- 4: VectorChord 0.4: Faster PostgreSQL Vector Search with Advanced I/O and Prefiltering
- 5: VectorChord 0.3: Bringing Efficient Multi-Vector Contextual Late Interaction in PostgreSQL
- 6: VectorChord 0.2: 60K-Dimensional Vectors, 50% Faster Indexing with ARM
- 7: pgvecto.rs 0.2: Unifying Relational Queries and Vector Search in PostgreSQL
1 - VectorChord 1.1: Native 4/8 Bit Vector Types and Per-Index Query Defaults
We’re excited to announce the release of VectorChord 1.1 as we kick off the new year of horse.
VectorChord 1.0 was a milestone for Postgres-native vector search: it made large-scale indexing fast enough to feel like iteration, not an outage. In 1.1, we’re building on that foundation with RaBitQ8: A new vector type that delivers 4x storage savings and faster search speeds compared to float32, all with less than 1% recall loss. Paired with RaBitQ4 and more composable query control, VectorChord 1.1 is ready for your most demanding production workloads.
This release focuses on two pain points we’ve observed through community feedback:
-
Capacity constraints. When vector indexes grow massive, scaling isn’t just about throughput. It is also about SSD footprint and buffer cache pressure.
-
Operational Overhead. As the number of indexes grows, manually setting search parameters (like nprobe) for every query clutters your application logic. This becomes a major headache in scenarios like partitioned tables, where individual indexes need distinct configurations. Relying on a global session variable (GUC) makes it impossible to tune these indexes independently.
VectorChord 1.1 addresses both. We’re introducing rabitq8 and rabitq4, native quantized vector types that are 4x and 8x smaller than standard float32. These types shrink total index size by 4x–7x, drastically reducing storage overhead. We’ve also added per-index query defaults, allowing multi-index queries to rely on specific configurations rather than a brittle global PostgreSQL GUC.
RaBitQ8 & RaBitQ4: Low bit vector type for storage efficiency
Vector data footprint is the hidden limiter of large-scale search on Postgres. Storing high-dimensional vectors as standard float32 (4 bytes per dimension) consumes massive amounts of SSD space and memory. As this footprint grows, it increases buffer cache pressure and forces queries to read from disk, causing P99 latency to spike.
VectorChord 1.1 solves this with two new quantized data types: rabitq8 and rabitq4, built on extended RaBitQ (paper). By using 8-bit and 4-bit representations instead of 32-bit floats, these types reduce per-vector storage by 4x and 8x respectively, while keeping accuracy loss minimal.
Using these types is almost identical to using vector. The only difference is that you quantize values with quantize_to_rabitq8 or quantize_to_rabitq4 during INSERT and SELECT.
On LAION with 100M 768-dimensional vectors, a typical vector (float32) index occupies about 400GB. Using the halfvec (float16) type reduces that to roughly 171GB. Under the same index options, switching to rabitq8 further reduces it to about 95GB, and rabitq4 to around 58GB, delivering a 4x to 7x footprint reduction compared with the baseline.

The next question is the recall and throughput trade-off. rabitq8 delivers the index size reduction while keeping recall and QPS essentially on par with the baseline (float32 vectors). rabitq4 is a more aggressive option. It trades a larger recall loss for the smallest possible index size, and is best suited for deployments where storage is the primary constraint.

Per-Index Query Defaults: Composable Multi-Index Queries
In VectorChord, the vchordrq.probes GUC controls how much of the vector space is searched at query time, directly trading off throughput against recall. For hierarchical vchordrq indexes, vchordrq.probes must have the same length as the build.internal.lists configuration used at build time. Typical configurations look like:
build.internal.lists |
vchordrq.probes |
|
|---|---|---|
| No partition | [] |
'' |
| 1-layer partition | [2000] |
'40' |
| 2-layer partition | [800, 640000] |
'40,200' |
For simple vector search on a single table with a single index, setting the GUC once before running a query is a natural choice.
However, the situation changes when a single query touches more than one vector index. Indexes built with different build.internal.lists configurations should logically use different probes settings. Worse, when the number of list levels differs, no single global probes value can simultaneously match both indexes, making the global setting inherently unsuitable for such queries.
To solve this, VectorChord 1.1 introduces per-index query defaults as index options, following PostgreSQL’s per-index configuration model. Instead of forcing every query to share a single global configuration, each index can now define its own defaults, which take effect when a global configuration is not explicitly set.
You can set per-index defaults at index creation time, and modify them at any time without rebuilding the index.
In addition to vchordrq.probes, other query-time parameters can also be given per-index defaults at index creation time, so multi-index queries can rely on independent, index-specific settings. For the full list of configurable parameters, see Fallback Parameters.
Summary
VectorChord 1.1 makes large-scale deployments easier to run. rabitq8 and rabitq4 significantly reduce storage size, lowering storage and memory pressure while preserving a familiar SQL usage pattern. Per-index fallback query defaults make multi-index vector queries possible within a single statement, especially when those indexes are built with different options.
Whether you are hitting storage and memory limits in real-world workloads or running complex queries with multiple vector indexes, we invite you to upgrade to VectorChord 1.1, try it on your own workloads, and share your feedback.
-
Download/Star on GitHub: https://github.com/tensorchord/VectorChord
-
Join the Community: https://discord.gg/KqswhpVgdU
2 - VectorChord 1.0: Developer-First Vector Search on Postgres, 100x Faster Indexing than pgvector
Two years ago, when we published the very first pgvecto.rs blog post, we made a bet: Postgres is the best place to do vector search. Since then we’ve been iterating on that bet — from VBASE with filtered vector search, to longer vector support, to the RaBitQ quantization scheme and disk‑friendly index layouts.
With VectorChord 1.0 we’re moving the needle again. On a 16 vCPU machine, we can now build an index over 100M vectors in under 20 minutes. On the same scale, pgvector needs more than 50 hours. That number sounds impressive, but the point of this release isn’t just to win a benchmark slide. It’s to make your actual development and iteration loop much faster.
This post is organized into three parts:
1. Simplicity over complexity: breaking the “HNSW is always better” myth
When people first talk to us about VectorChord, one of the most common questions is very direct:
“Are you using HNSW? I heard HNSW is always better than IVF.”
On paper, HNSW is a beautiful algorithm. In many isolated benchmarks it wins. But we don’t run vector search inside a vacuum — we run it inside Postgres, with its own storage model, vacuuming, MVCC, and operational habits.
If you look at it from that angle, the trade‑off changes a lot.
The Postgres reality of HNSW
HNSW uses a layered graph structure. Every new vector is a node that may connect to several other nodes across multiple layers. Every delete potentially removes a node that many other nodes depend on.
In a stand‑alone vector engine you can design the entire storage engine around this structure. Inside Postgres, you can’t. You have to live inside the existing table/index model, work with vacuum, and behave well under MVCC.
That’s where the pain starts:
-
Insertions are heavy. Inserting a single vector into an HNSW index can trigger cascades of changes across multiple nodes and layers. Under high write load this makes it harder to keep latency stable.
-
Deletions are subtle. In practice, a delete often just marks a node as dead but leaves it in the graph so connectivity isn’t broken immediately. As more nodes are marked this way, search still walks through them, which adds extra latency when a large fraction of the graph is “dead but still present.”
-
Vacuum pays the real price. You can’t simply drop those nodes, because removing them outright would break neighborhoods and disconnect parts of the graph. To fix that, pgvector has to reinsert all the neighbors of a dead node so the graph stays connected without it. That reinsertion work is what makes maintenance expensive; the core issue isn’t just reclaiming dead tuples, it’s re‑wiring the graph around every deleted node.
None of this is impossible, but it pushes you toward high cost whenever you have frequent updates.
Why we chose IVF + RaBitQ instead
VectorChord’s core index is IVF + RaBitQ with simple posting lists. Vectors are routed into coarse clusters, and inside each cluster we store a tiny quantized code instead of a 768‑dimensional float. At query time almost all the work happens on these bit‑packed codes, using table lookups and cheap integer math.
Because the index mostly scans compressed codes, a posting‑list scan stays fast even when it touches many entries. In our benchmarks this makes VectorChord clearly faster than a naïve IVF that compares full‑precision vectors, and still faster than pgvector’s HNSW index, which walks its graph and scores neighbors with full‑precision arithmetic.
People sometimes ask “what about HNSW + quantized vectors?” You can do that, and it can speed up the first phase of a search, where you traverse the quantized vectors and pick candidates. But you still need a second phase that fetches and scores full‑precision vectors based on those candidates, and that part doesn’t care which index you used. In typical workloads the first phase is only about 40% of total latency, so even a 2x faster scan would only cut end‑to‑end time by roughly 20% — and because HNSW can’t lay out data in the tight, batch‑friendly fast‑scan format, even that theoretical gain may be hard to realize in practice.
With IVF + RaBitQ the postings are just arrays of compressed entries. Inserts append a new code; deletes clear a code. There is no global graph to repair, so frequent updates don’t trigger cascades of work. Operationally it behaves like a normal index, and in our tests this design handles around 10x the update throughput of pgvector’s HNSW index while keeping latency stable. For additional performance numbers — especially around query performance — please see our earlier blogs Vector Search Over PostgreSQL: A Comparative Analysis of Memory and Disk Solutions.
Most importantly, this simplicity is what enables the improvements in the next sections. If your index structure is already incredibly intricate, every extra optimization adds more moving parts. By keeping the core design simpler, we gave ourselves room to make index builds and developer workflows dramatically better.
2. Making indexing feel like iteration, not an outage
Let’s talk about the number in the title: 100x faster indexing than pgvector.
On paper, the comparison looks like this on LAION 100M‑vector dataset:
-
pgvector: more than 50 hours of index build time on 16 vCPUs (and it may fail if memory is insufficient).
-
VectorChord 0.1: KMeans done externally in about 2 hours on a GPU; insertion in Postgres taking around 20 hours on 4 vCPUs.
-
VectorChord 1.0: KMeans and insertion both done inside Postgres, finishing in under 20 minutes on 16 vCPUs (about 8 minutes for KMeans + 12 minutes for insertion).
But what changes for you is much simpler:
-
In the pgvector world, indexing a large dataset is a multi‑day event. You plan around it, you babysit it, you worry about what happens if it fails.
-
In the VectorChord 1.0 world, a full rebuild is closer to “run it before lunch and check the results after coffee.”
We got there by attacking both phases of IVF building: the KMeans step that finds centroids, and the insertion step that assigns every vector to its nearest centroid.
To get there, we tackled the problem instead of just the code. First, instead of micro‑optimizing a naïve 768‑dimensional, 160,000‑centroid KMeans over 100M points, we project vectors down to a much smaller space with Johnson–Lindenstrauss Lemma, which cuts the KMeans compute and memory footprint by roughly 7x. Second, we run hierarchical KMeans in two stages so we only ever cluster smaller subsets of the data instead of 160,000 centroids at once, which accelerates 400x in theory. For insertion, we reuse the same idea one level up by building an IVF over the centroids themselves, so each data vector only compares against a small set of candidate centroid buckets using quantized codes. Together these changes move most of the work out of CPU‑bound distance math: for a 100M‑vector build the dominant cost becomes Postgres allocating and writing index pages at roughly the SSD limit. After tightening the allocation path and lock granularity so we can stream pages out in large chunks, the practical result is that a full rebuild fits comfortably into minutes instead of days. For more details, we’ve written a dedicated blog How We Made 100M Vector Indexing in 20 Minutes Possible on PostgreSQL to explain the technical detail.
These optimizations can be done easily with the following SQL:
3. Features built for developers, not just for a benchmark chart
VectorChord 1.0 also adds a set of features that barely show up in benchmarks, but matter a lot when you live with the system every day. They’re all about helping you understand how your index behaves, and about letting you use modern models and deployments without friction.
Built‑in monitoring of index quality
All approximate nearest‑neighbor indexes drift over time. Data distributions change, and what was a great index at build time might quietly degrade.
Instead of leaving you to guess, VectorChord can continuously measure recall for you. It automatically samples real query vectors, re‑evaluates their neighbors with a more exact method, and tracks how often the index returns the “right” answers.
This turns a vague feeling — “search seems a bit off lately” — into a graph you can look at. If recall is steady, you know you can postpone a rebuild. If it’s trending down, you can plan a rebuild before users notice. It also gives you something concrete to feed into your existing observability stack, or into Prometheus so you can keep an eye on recall on the same dashboards as your other SLOs.
In practice, you can evaluate recall for a real query pattern with a single SQL call, and then export that number as a metric. For example:
Long vector support so you don’t have to cripple your model
We support vectors up to 16,000 dimensions. That sounds like a dry specification, but it has a clear practical effect: you can plug in newer models, including long‑context or multimodal ones, without immediately needing to compress or truncate their outputs just to make the index happy.
You can start with the representation your model naturally produces, get a feel for performance and quality, and then decide whether you want to apply more aggressive quantization or dimensionality reduction. The index shouldn’t be the thing forcing you to compromise on model choice.
Multi‑vector retrieval for richer RAG
Not every document fits into a single vector. Modern retrieval‑augmented generation (RAG) systems often represent a passage as a set of vectors — for example, one per token or one per sentence — and then compare that set to a set of query vectors. This “late interaction” style is usually called multi‑vector retrieval.
VectorChord supports this pattern natively via a MaxSim‑style operator over arrays of vectors. Conceptually, for each query vector you look for the best‑matching document vector, take their dot product, and then sum those best scores. In VectorChord this is exposed as the distance‑based @# operator on vector[] columns: the left‑hand side is the document’s vector array, the right‑hand side is the query’s vector array.
Getting started looks very similar to single‑vector search. You store an array of vectors per row and build a dedicated index:
At query time you pass in an array of query vectors and order by the @# score:
Under the hood VectorChord applies its ANN machinery to these vector arrays, so you get the expressiveness of multi‑vector models with the same kind of performance you expect from single‑vector IVF indexes — all inside Postgres and plain SQL.
Multi‑platform SIMD
VectorChord ships with SIMD acceleration for x86_64, ARM and IBM architectures. At runtime we detect the best available instruction set — AVX512 and friends where available — and use it without you having to tune build flags or keep separate binaries.
Experimental DiskANN + RaBitQ
We also have an experimental index type combining DiskANN with 2‑bit RaBitQ. On some datasets and recall targets it can deliver higher QPS than IVF + RaBitQ. The trade‑off is that indexing and updates are noticeably slower and more complex.
We don’t recommend this as the default choice. It’s there for teams who have very specific workloads, know exactly what they are doing, and are willing to pay higher operational costs for more QPS in a narrow slice of the parameter space. For everyone else, IVF + RaBitQ remains the recommended workhorse.
Similarity filters that stop scanning early
Sometimes you don’t just want the nearest neighbors; you want “everything within this radius, up to N rows.” The most natural way to write that in SQL is with a distance in the WHERE clause, plus ORDER BY and LIMIT:
This returns the right answers, but it performs poorly when only a few points fall inside the radius. Postgres still has to keep scanning the index until it finds ten rows or exhausts the search space, because the distance check is just a filter applied after the ANN scan.
VectorChord adds a “similarity filter” syntax that lets the distance threshold be pushed down into the index itself. You wrap the query vector and radius in a sphere() value, and use the <<->> operator so the index knows it can stop as soon as the search region moves beyond that sphere:
Prefilter and postfilter so queries match your data model
In real applications, vector search almost never happens in isolation. You filter by tenant, permissions, time ranges, or content type, then rank by vector similarity, or sometimes the other way around.
VectorChord lets you choose between prefiltering and postfiltering at the index level. In low‑selectivity scenarios, prefiltering can reduce the candidate set enough to get up to roughly five‑fold QPS improvements. In other cases you might want to search first and filter only the top results for better recall. The important part is that you can express both patterns naturally in Postgres.
Enabling prefiltering for a session is a single SQL statement:
Text search with VectorChord‑BM25
Finally, we added a VectorChord‑BM25 extension that brings strong text search directly into your Postgres instance. It supports multiple languages and advanced tokenization, and aims to be competitive with ElasticSearch‑style relevance for many workloads.
The idea is not to replace every dedicated search engine, but to let you build systems where BM25 and vector search live side by side, inside the same database, using the same operational tools. For many teams that alone removes a lot of deployment and maintenance burden.
In practice you can call it from plain SQL, combine it with your embeddings, and order by a unified score. For example:
Closing thoughts
VectorChord 1.0 is easy to summarize as “100x faster indexing than pgvector on 100M vectors.” That headline is true, but it is not the main story.
Our goal is to make VectorChord one of the best ways to do retrieval on Postgres, from the first prototype to billion‑scale datasets. If you’re already using pgvector, we’d love you to try VectorChord 1.0 on your real workloads and tell us where it helps and where it can do better. We would also like to express our appreciation to the EnterpriseDB team for their valuable feedback throughout this work.
3 - VectorChord 0.5: New RaBitQ-empowered DiskANN Index and Continuous Recall Measurement
We’re thrilled to announce the release of VectorChord 0.5! This release marks a significant step forward in our mission to provide more flexible, powerful, and controllable vector search capabilities. In the 0.5 release, we’re introducing two major updates: experimental support for the DiskANN graph index and a new recall measurement tool to monitor the health of your IVF+RaBitQ indexes proactively.
New Index Preview: RaBitQ-empowered DiskANN Index
From day one, VectorChord’s core indexing solution has relied on a powerful combination: the cluster-based IVF algorithm and RaBitQ quantization—what we ship as vchordrq (IVF+RaBitQ). This approach consistently delivers excellent low-latency, high-recall performance across a wide range of use cases and remains our recommended default for most scenarios.
At the same time, we recognize that graph-based indexes can outperform IVF+RaBitQ on certain datasets and at specific (often higher) recall targets. To give you the best tool for every job—and because our goal is to be a one‑stop solution for vector search—VectorChord 0.5 introduces experimental support for the DiskANN algorithm as an additional option.
What is DiskANN and Why Does It Matter?
Traditional top-tier graph algorithms (like HNSW and NSG) achieve their speed by keeping the entire graph in memory, which drives up hardware costs and caps single-node scale. SSDs are cheaper, but historically their random I/O made on-disk graphs impractical without big latency penalties.
DiskANN’s mission is to break this memory barrier. It’s a graph ANN designed from the ground up to store and search billion-scale datasets on inexpensive SSDs while maintaining competitive recall and low latency.

A visualization from the original DiskANN paper.
How our variant differs
We implement a variant of the original DiskANN design: instead of the paper’s default Product Quantization (PQ), our implementation uses RaBitQ as the quantization layer. RaBitQ is more accurate and comes with theoretical guarantees, which helps us deliver better recall–latency trade‑offs compared with vanilla PQ used in original implementations. In practice, this change enables stronger accuracy at the same footprint or faster queries at the same recall.
In VectorChord 0.5, we’ve integrated DiskANN into the existing ecosystem so you can evaluate it side-by-side with vchordrq.
When DiskANN Can Shine
-
Workload + target dependent gains. For some model families (e.g., OpenAI/Cohere‑style embeddings) and high-recall settings, DiskANN can deliver lower latency and/or higher recall than IVF+RaBitQ on the same hardware.
-
Stable and predictable build memory. It avoids the KMeans phase of IVF, reducing memory fluctuations during index build and simplifying capacity planning.
-
Ecosystem compatibility. Keep using VBase for metadata filtering and RaBitQ quantization for smaller footprint and faster re-ranking.
Important Considerations (Read This First)
DiskANN is still experimental in VectorChord, and—like all graph ANN methods—it entails trade‑offs:
-
Updates & build speed. Index builds and updates are much slower than with vchordrq (IVF+RaBitQ). If you have frequent inserts/deletes or need fast rebuilds, vchordrq is the better fit.
-
Dynamic data performance. Modifying graph connectivity is computationally heavier than updating IVF lists; expect better operational ergonomics with vchordrq for mutable datasets.
-
Operational simplicity. vchordrq tends to be simpler to tune and operate for most teams.
Our recommendation: Start with vchordrq (IVF+RaBitQ) for the majority of use cases. Consider DiskANN when you’re chasing top‑tier recall on relatively static corpora, want tighter tail latency at high recall, or when build‑time memory predictability is a hard requirement. Your feedback will help us harden this option for production.
How to Get Started
Check out our official documentation for detailed instructions on configuring and using the new graph index: Guide to Using Graph Index in VectorChord
Proactive Monitoring: Recall Measurement Tool for IVF+RaBitQ
A potential challenge with vector search index is “data distribution drift”. As you continuously add new data—especially when the new data’s vector distribution differs significantly from the initial dataset—the index’s recall can degrade over time, impacting query quality.
Previously, quantifying this degradation was difficult, often relying on intuition or complex offline evaluations to decide when an index rebuild was necessary.
To empower you to proactively and easily monitor your index’s health, version 0.5 introduces a powerful new function: vchordrq_evaluate_query_recall.
This function allows you to use a small, representative set of query vectors and their ground truth nearest neighbors to quickly and accurately assess the actual recall of your current IVF+RaBitQ index.
What It Does For You:
-
Quantify Performance: Turn the “feel” of your index’s quality into a hard, measurable number.
-
Inform Decisions: By running evaluations periodically, you can clearly visualize the recall trend and make data-driven decisions on when to rebuild your index for optimal performance.
-
Enhance Service Quality: Ensure your live vector search service consistently meets its quality SLAs and prevent business impact from silent index degradation.
How to Use It
Here’s how to put it into practice:
For more details and configuration, you can refer to Measuring Recall for IVF+RaBitQ Indexes
Automatically Record Queries for Recall Tracking
Keeping a high-quality vector search service isn’t just about measuring recall once—it’s about measuring it continually on real traffic. Starting in v0.5.2, VectorChord can automatically record (sample) your production queries so you can evaluate recall on the exact vectors users searched for.
Why it matters
-
Hands‑off data collection: No custom logging pipelines or app changes.
-
Representative signals: Evaluate recall on the same distributions your system sees in production.
-
Privacy‑aware & lightweight: You control when sampling is enabled and how much to collect.
Enable query sampling
After enabling, run your normal vector searches (e.g., SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 10;). VectorChord will capture the essential components of each sampled query: schema, index, table, column, operator, and vector value.
Inspect what was recorded
Evaluate recall on recorded queries
Note: If you run PostgreSQL replication with primary/standby servers, sampled queries are not synchronized via replication or backup. Each server records its own queries based on the traffic it serves.
Summary
VectorChord 0.5 brings unprecedented flexibility to our users. The experimental DiskANN support offers a new high-performance option for specific workloads, while the recall measurement tool gives you fine-grained monitor over the operational health of your existing IVF indexes.
We believe that empowering users with more choices and greater control is the driving force behind VectorChord’s evolution. We sincerely invite you to try out the new version and share your feedback, especially on how DiskANN performs in your real-world scenarios.
-
Download/Star on GitHub: https://github.com/tensorchord/VectorChord
-
Join the Community: https://discord.gg/KqswhpVgdU
Ready to take it for a spin? Head over to our GitHub repository, download the latest release, and see what VectorChord 0.5 can do for you
%[https://github.com/tensorchord/VectorChord/]
4 - VectorChord 0.4: Faster PostgreSQL Vector Search with Advanced I/O and Prefiltering
We’re excited to announce the release of VectorChord 0.4, a significant update that enhances high-performance vector search within PostgreSQL. We believe this release pushes the boundaries of what’s possible for vector search in PostgreSQL, introducing key architectural improvements designed to lower latency and increase throughput for demanding, real-world workloads.
If you’re working with similarity searches, RAG pipelines, or other AI-driven applications on PostgreSQL, these updates are for you. We’ve focused on two major areas: significantly enhancing I/O for cold queries by leveraging PostgreSQL’s evolving capabilities, and optimizing filtered vector searches.
🚀 Major Improvement 1: Advanced I/O for Disk-Bound Indexes (2x-3x Lower Cold Query Latency!)

VectorChord has supported disk-based indexing since its early versions. Previously, a challenge was I/O efficiency, as full-precision vectors were read one-by-one due to limitations in PostgreSQL’s older internal APIs for buffer operations.
VectorChord 0.4 addresses this with a rewritten page layout and the adoption of modern streaming I/O techniques. We’re proud to be one of the first, if not the first, PostgreSQL extensions to adopt these new streaming I/O APIs as they become available. This allows us to pipeline I/O with computation and issue disk I/O operations more effectively. As a part of this effort, we’ve also contributed initial PostgreSQL 18 support to the pgrx framework to enable testing and development with these upcoming AIO capabilities, benefiting the wider PostgrSQL community.
Our approach adapts to your PostgreSQL version:
-
On PostgreSQL 17 (and newer with
io_method=sync): Utilizingmadvisefor Prefetching When VectorChord calls PostgreSQL’s new streaming I/O APIs, PostgreSQL’s underlying implementation on PG17 (or PG18 with io_method=sync) may internally use madvise(MADV_WILLNEED). This hints the OS kernel about upcoming data needs, enabling reads from disk to be cached in memory with page cache first. When actual I/O occurs, PostgreSQL can read directly from the page cache instead of waiting for disk I/O. -
Preparing for Asynchronous I/O: PostgreSQL 18 &
io_uringLooking ahead to PostgreSQL 18’s true Asynchronous I/O (AIO) withio_uring, VectorChord 0.4 is engineered for integration. This will allow data to be fetched directly into PostgreSQL’s shared buffers with minimal overhead and maximal efficiency. -
For Earlier PostgreSQL Versions (Pre-PG17): Streaming I/O Interface for Prefetching For users on older PostgreSQL versions, we’ve implemented a similar streaming I/O interface within VectorChord for backward compatibility. While it doesn’t leverage kernel-level AIO or the newest PostgreSQL internal APIs, this interface allows us to achieve effective prefetching of buffers. This means users on earlier PostgreSQL versions can also benefit from the improved I/O patterns and reduced latency when fetching full-precision vectors.
The Impact of Advanced I/O for Disk Indexes: These I/O enhancements result in a 2x-3x reduction in latency for cold queries in our benchmarks. This directly improves tail latency, especially when queries require re-ranking with disk-resident vectors.

🎯 Major Improvement 2: Pre-filtering for Faster Filtered Searches (Up to 3x Faster!)

Vector search is often combined with metadata filtering. Addressing this efficiently has been a key focus for us. We were among the first to tackle the vector filtering challenge in PostgreSQL by introducing VBASE-style filtering in pgvecto.rs, which significantly improved performance over pgvector.
Now, with VectorChord 0.4, we’re pushing the performance to the next level by introducing robust prefiltering support.
-
Post-filtering (Previous Method): Find top-K vectors, then filter. Inefficient for selective filters.
-
Pre-filtering (New in 0.4): Based on bit vector scan results, identify rows satisfying metadata filters first, then perform vector distance calculations only on this smaller set.
We now use efficient mechanisms with quantized bit-vector scans to identify matching rows before vector distance computations. Since filter checks are much lighter than distance calculations, this provides a significant speedup. User can enable this with SET vchordrq.prefilter=ON.
The Impact: Our benchmarks show up to 3x faster search performance when pre-filtering is applicable, compared to our already optimized VBASE post-filtering approach. This offers considerable advantages for complex queries.

✨ Other Notable Improvements:
-
Optimized Residual Quantization (~20% QPS Boost): Thanks to Jianyang (author of RaBitQ), we’ve refined residual quantization. By reformulating
<o, q-c>as<o, q> - <o, c>, the query vectorqis quantized only once, yielding a ~20% QPS improvement. We now recommend user to enable residual quantization for L2 distance. -
Optimized Rotation Matrix & Simplified Configuration: Also thanks to Jianyang, a new Fast Hadamard Transform optimizes rotation matrices and removes the
prewarm_dimGUC, simplifying configuration and slightly speeding up the process. -
Rewritten Documentation: We’ve comprehensively rewritten our documentation, now offering more user guidance and a detailed API reference to help you get the most out of VectorChord. Check https://vchord.pgsty.com/docs/.
Get Started with VectorChord 0.4!
We believe this release significantly enhances vector search capabilities in PostgreSQL.
-
Download/Star on GitHub: https://github.com/tensorchord/VectorChord
-
Join the Community: https://discord.gg/KqswhpVgdU We encourage you to try VectorChord 0.4, benchmark it with your workloads, and share your feedback.
Happy Vector Searching!
5 - VectorChord 0.3: Bringing Efficient Multi-Vector Contextual Late Interaction in PostgreSQL
We’re thrilled to announce the release of VectorChord 0.3, a major milestone that significantly boosts the performance and applicability of advanced vector search techniques directly within your Postgres database! Building on our 0.2 release, which brought ARM support and faster indexing, version 0.3 tackles one of the biggest hurdles in modern retrieval: efficient multi-vector search with late interaction.
Beyond Single Vectors: Why Multi-Vector Rocks
For years, vector search primarily represented entire documents or queries as single, dense vectors. While powerful, this approach involves averaging or compressing complex information into one representation, inevitably leading to a loss of nuance. Imagine trying to capture the entire meaning of a detailed technical document in a single sentence – you’d lose specifics!
Enter multi-vector representations and late interaction, pioneered by models like ColBERT. Instead of one vector per item, these models generate multiple vectors – often one for each token (word or sub-word). The real magic happens during the search process:
-
Query Encoding: Your search query is also broken down into multiple token vectors (let’s call them q1, q2, …, qN).
-
Document Encoding: Similarly, the document is represented by its token vectors (d1, d2, … dM).
-
Late Interaction & MaxSim Aggregation: Instead of one comparison, we perform fine-grained matching. The core idea is the Maximum Similarity (MaxSim) operation. For each query token vector (like q_i), we find the document token vector (d_j) that has the highest similarity (e.g., cosine similarity or dot product) to it across all document tokens (d1 through dM). This process is repeated for every query token (q1, q2, …, qN). The final relevance score for the document is then calculated by summing up these maximum similarity values obtained for each query token. This operation is inherently asymmetric, focusing on how well each part of the query is represented somewhere in the document.
Why is this better?
-
Contextual Nuance: Late interaction with MaxSim allows the model to capture fine-grained semantic relationships. It can identify if specific important terms from the query strongly match specific parts of the document, rather than relying on a potentially diluted overall average similarity.
-
Improved Relevance: By considering focused, token-level interactions and summing the best matches for each query term, models like ColBERT achieve state-of-the-art retrieval quality. This fine-grained approach is particularly powerful for content-rich queries with multiple terms, leading to a better understanding of user intent. On the BEIR benchmark, this translates to a significant performance boost: With the same ModernBert model, Colbert variant achieves 51.6 NDCG@10 compared to 41.6 for dense vector variant.
Our previous blog post explored using ColBERT for reranking, showcasing its power:
Supercharge Vector Search with ColBERT Rerank in PostgreSQL
VectorChord 0.3: Bringing Efficient MaxSim to Postgres, Inspired by WARP
VectorChord 0.3 directly confronts the high computational cost of late interaction. We’ve integrated a highly optimized multi-vector late-interaction MaxSim operator and index into our core Rust engine, drawing inspiration from the groundbreaking WARP engine (Paper: WARP: An Efficient Engine for Multi-Vector Retrieval, Code: jlscheerer/xtr-warp).
The genius of the WARP approach lies in a fundamental insight: the complex multi-vector MaxSim calculation (comparing N query vectors to M document vectors) can be cleverly decomposed into multiple, independent single-vector search processes. Instead of one massive N x M comparison, WARP effectively performs N separate searches, one for each query token vector, against the indexed document vectors to find its best match.

Our core improvement in VectorChord 0.3’s MaxSim scanner is built on this concept. We’ve implemented MaxSim by leveraging and orchestrating VectorChord’s existing, highly optimized single-vector search infrastructure. When a MaxSim query is executed with an index, VectorChord performs multiple single-vector searches—one for each query vector—using our underlying index structures (IVF combined with RaBitQ). It then efficiently aggregates the results based on the MaxSim summation rule. For estimating missing values, we adopt the approach from WARP, using the distance to the centroid and the cumulative cluster size to estimate MaxSim scores for potential candidates.

Reusing our optimized single-vector search components ensures MaxSim benefits from existing performance tuning and stability. Importantly for users, it provides a seamless experience: you can leverage the same familiar index types (IVF with RaBitQ) for both single-vector and multi-vector MaxSim search, without needing a separate system. VectorChord 0.3 proudly stands as the first Postgres extension to deliver this efficient, decomposed MaxSim implementation, making state-of-the-art multi-vector retrieval practical and performant directly within your database.
Powerful Use Cases Unlocked
This new efficiency opens the door to practical implementations of cutting-edge techniques:
-
High-Performance ColBERT Reranking: Apply ColBERT’s superior relevance ranking to a candidate set retrieved by a faster first-stage search (like traditional vector search or keyword search) without incurring prohibitive latency penalties. Get the best of both speed and quality.
-
OCR-Free Document Search (ColPali/ColQwen): Imagine searching directly within scanned documents, PDFs, or images without needing a separate, often error-prone, OCR (Optical Character Recognition) step. Models like ColPali or ColQwen generate token embeddings directly from image patches. With VectorChord 0.3’s efficient MaxSim, you can now perform late-interaction search over these visual token embeddings directly in Postgres, enabling powerful search over documents previously inaccessible to pure text-based methods.
Stay tuned! We have another article coming soon, diving deep into how VectorChord 0.3 enables revolutionary OCR-free RAG pipelines.
Performance Highlights
We put VectorChord 0.3’s new multi-vector MaxSim capabilities to the test on the FiQA (Financial Opinion Mining and Question Answering) dataset. This standard benchmark includes 57,000 documents with approximately 15 million cumulative tokens.
Our initial benchmark results, using ColBERTv2 powered by VectorChord’s optimized engine, show promising performance:
-
Relevance: We achieved an NDCG@10 score of 34.1. This compares favorably to the 33.6 NDCG@10 reported for the same dataset in the original WARP paper.
-
Speed: Queries were executed efficiently, averaging just 35 milliseconds per query.
While these are preliminary results based on a single dataset as we continue optimization, they demonstrate VectorChord 0.3’s potential. Users can now leverage the advanced relevance capabilities of multi-vector search and late interaction with impressive speed, approaching the latency often associated with simpler single-vector methods, all directly within their Postgres database.
Get started with VectorChord 0.3
Prerequisites:
- PostgreSQL server with the VectorChord v0.3 installed
You can use our VectorChord-Suite image:
Step 1: Create a Table for Multi-Vector Data
First, define a table to store your data. The key difference is using the array type for your vector column (vector[]) to hold multiple vectors per row.
Step 2: Insert Multi-Vector Data
Insert data into your table. The vecs column takes a PostgreSQL array containing vector types.
Step 3: Create a vchordrq Index with MaxSim Support
To accelerate MaxSim searches, create an index using the vchordrq method and specify the vector_maxsim_ops operator class. A crucial parameter here is build.internal.lists.
- Calculate
n: Estimate the total number of individual vectors across your entire dataset.
- Set
lists: The recommended range forbuild.internal.listsis
Choose a value within this range (often powers of 2 work well).
Step 4: Configure Search Parameters (Optional but Recommended)
Before querying, you can tune runtime parameters for performance and accuracy:
-
vchordrq.probes: Controls how many index lists (clusters) are checked during a search. Higher values increase accuracy (recall) but slow down the search. A common starting point for finding the top 10 results (LIMIT 10) is 32. -
vchordrq.maxsim_refine: Limits the number of vector pairs re-computed with the original precision (otherwise will use the bit distance) for each candidate query token vector. It’s related to theprobes, a value of 20% of probed vectors will be sufficient.
Step 5: Perform a MaxSim Similarity Search
Now you can query using the @# MaxSim operator. Provide your query vectors as a PostgreSQL array of vector types.
You’ve now successfully set up a table, indexed it for multi-vector MaxSim search, and executed your first query using VectorChord 0.3’s MaxSim operator! Experiment with the probes and max_maxsim_tuples parameters to find the best balance of speed and accuracy for your specific use case.
%[https://github.com/tensorchord/VectorChord/]
6 - VectorChord 0.2: 60K-Dimensional Vectors, 50% Faster Indexing with ARM
Today, we’re thrilled to share VectorChord 0.2—a release shaped by community feedback and designed to tackle the evolving challenges of vector search in PostgreSQL.
%[https://github.com/tensorchord/VectorChord/]
Optimized Storage Layout: Supporting Up to 60,000 Dimensions
In PostgreSQL, the foundational storage unit is an 8KB page. While this design is robust for many workloads, it introduces constraints for modern use cases like high-dimensional vector search. For instance, pgvector faces a hard limit of 2000 dimensions per vector due to this fixed page size, as larger vectors cannot be indexed within a single page.
To address this, we’ve reimagined the vector storage architecture in VectorChord. By redesigning how vectors are internally laid out, we enable precise control over storage allocation, allowing vectors to span multiple pages when needed. Now, we can support vectors with a limit of up to 60,000 dimensions.
| System | Vector Dimension Limit |
|---|---|
| VectorChord 0.2 | 60000 |
| VectorChord 0.1 | 1600 |
| pgvector | 2000 |
This cross-page capability not only lifts the 2000-dimension barrier (now supported in v0.2) but also optimizes storage efficiency. For example, a 1200-dimensional vector (occupying ~4.8KB) would traditionally waste nearly half a page’s space in PostgreSQL, since only one such vector fits per 8KB page. This results in just ~58.5% storage utilization (1200 dim × 4 bytes ÷ 8192 bytes). By tightly packing vectors across page boundaries, VectorChord minimizes unused space and improves storage density.

While this is a small step forward, we’re excited about the possibilities it unlocks for scalable vector workloads.
Float16 & ARM
In version 0.2, we’re excited to introduce Float16 support, giving users the flexibility to balance storage efficiency with recall accuracy. By opting for Float16, you can reduce vector storage requirements by 50%, though this comes with a modest trade-off in recall performance. We want to clarify that this optimization applies only to raw vectors—quantized vectors still require 1 bit per dimension to faithfully represent the original data. This update empowers users to make thoughtful choices based on their specific accuracy and storage needs.
We’ve also prioritized performance improvements for ARM architectures. By rewriting distance calculations and Fast Scan logic using ARM’s Scalable Vector Extension (SVE) instruction set, VectorChord now delivers optimized performance on ARM-based systems. This enhancement ensures that users on platforms like AWS’s latest i8g instances (powered by Graviton4 processors) can achieve faster throughput at the same cost as older i4i instances. While these optimizations are incremental, we’re thrilled to help teams scale efficiently in modern cloud environments.

As the results show, VectorChord running on the i8g.xlarge (ARM64) delivers about a 30% improvement in throughput compared to the i4i.xlarge, even though both are priced similarly. On the other hand, the more expensive i7ie.xlarge, which costs 50% more, only offers a modest 15% performance boost over the i8g—far from justifying its higher price tag. Additionally, the index construction time on the ARM-based i8g is significantly faster, which was a surprising and welcome advantage.
Our benchmarks highlight some insights for cost-conscious users. VectorChord on AWS’s i8g.xlarge (ARM64) achieves ~30% higher throughput compared to the similarly priced i4i.xlarge, demonstrating how modern ARM architectures can deliver meaningful performance gains without added cost. On the other hand, the i7ie.xlarge, priced 50% higher than the i8g, offers only a 15% performance uplift—a trade-off that may not align with most teams’ cost-efficiency goals.
We were also pleasantly surprised by the significantly faster index construction times on ARM-based i8g instances. While this wasn’t a primary focus of our optimizations, it underscores the broader potential of ARM64 and SVE for vector workloads. That said, we recognize these results are just one part of a larger ecosystem, and we’re eager to collaborate with the community to refine these benchmarks further.
Ultimately, our goal is to empower users with data-driven choices. The i8g’s strong performance-per-dollar and unexpected construction speed advantages make it a compelling option for teams scaling vector search in production. None of this would be possible without the incredible open-source ecosystem we build upon. We’re grateful for the community’s support and feedback as we continue refining VectorChord for real-world workloads.
Getting Started
You can use Docker to try out VectorChord 0.2.
All the query syntax is the same as VectorChord 0.1!
Summary
VectorChord 0.2 builds on its predecessor with a 30% smaller index size and 50% faster builds. Float16 supports halves of raw vector storage, while new features like 60000-dimensional vectors and ARM64 optimizations deliver smoother PostgreSQL retrieval. Together, these updates help users scale efficiently—without sacrificing performance.
We warmly welcome the community to explore VectorChord 0.2! Whether you’re optimizing storage with Float16, scaling high-dimensional workloads, or leveraging ARM’s cost-performance benefits, we’re here to support your journey. Your feedback shapes what’s next—let’s build smarter vector search, together. 🚀
Take these advancements further with VectorChord Cloud, offering a hassle-free managed service and a free trial to jumpstart your projects. Whether you’re optimizing storage, scaling complex workloads, or leveraging ARM’s efficiency, our cloud platform handles the infrastructure so you can focus on innovation.
7 - pgvecto.rs 0.2: Unifying Relational Queries and Vector Search in PostgreSQL
We are excited to announce the release of pgvecto.rs 0.2, a significant milestone in the journey of bridging the gap between relational queries and vector search in PostgreSQL. This update brings together the power of both worlds, offering enhanced efficiency and enabling complex queries within PostgreSQL.
In the past, developers and data scientists encountered the significant challenge of managing separate systems for relational queries and vector search. This resulted in increased complexity and resource overhead. However, with the release of pgvecto.rs 0.2, we have addressed this issue by integrating the cutting-edge VBASE method from OSDI 2023. This integration has substantially refined the efficiency of vector search within PostgreSQL.


Real-world applications: Immich
Real-world applications often require complex queries that go beyond simple Approximate Nearest Neighbor (ANN) search. To explore a practical example of such applications, let’s take a closer look at immich, a self-hosted photo and video backup solution that highlights the importance of advanced vector and traditional relational queries.

immich leverages advanced vector-based and relational queries to provide intelligent search capabilities. With immich, you can efficiently search and discover relevant media files based on visual similarity, metadata, and user-defined tags. The underlying technology powering this functionality is pgvecto.rs.
We will provide a concise overview of the search feature in immich. Consider a scenario where our database consists of three tables.
We have a table named AssetEntity that stores information about the images, including their unique identifier (id), the owner (ownerId), creation and update timestamps (createdAt and updatedAt), and other relevant attributes.
The ExifInfo table contains information specific to the EXIF data of the images, such as the latitude (lat), longitude (long), city, state, country, and description. The assetId column in this table establishes a relationship with the asset_entity table.
Additionally, we have the ImageEmbedding table, which stores vector-based embeddings for each image. The embedding column is an array of floating-point numbers representing the image embedding vector. The assetId column in this table also establishes a relationship with the asset_entity table.
The query statement below is used to search for images based on certain criteria and sorting by the similarity of the image embeddings. It joins the AssetEntity, ImageEmbedding, and ExifInfo tables, filters the results based on criteria like ownerId, isArchived, isVisible, createdAt, and city in the EXIF info, then orders the images by the similarity of the provided embedding. The query returns a limited number of results based on the specified limit.
It can be seen as a scenario involving Single-Vector TopK + Filter + Join operations. The limitations of pgvector in supporting such operations highlight the need for VBASE.
When it comes to Single-Vector TopK operations, pgvector falls short in providing efficient performance. TopK queries require finding the K nearest neighbors to a target vector, but pgvector struggles to predict the optimal value of K, leading to suboptimal query performance. VBASE, on the other hand, addresses this limitation by leveraging relaxed monotonicity and offering significantly higher efficiency. It provides a more accurate and efficient solution for single-vector TopK queries.
Additionally, pgvector’s support for Filter and Join operations in conjunction with vector queries is limited. Complex queries that involve filtering or joining on both scalar and vector data can be challenging to execute efficiently in pgvector. VBASE, however, is designed to handle these types of queries seamlessly. It integrates vector search systems with relational databases, allowing for the execution of complex queries involving filters and joins on both scalar and vector attributes. This capability makes VBASE a more suitable choice for applications that require these operations.
Benchmark
To evaluate the performance, benchmarks can be conducted to measure the efficiency and effectiveness of both systems. We utilize the laion-768-5m-ip-probability dataset for benchmarking purposes due to the absence of a comprehensive relational benchmark. The dataset is derived from LAION 2B images. It contains 5,000,000 vectors, 10,000 queries.

The dataset includes a probability column that stores random floating-point values generated from a uniform distribution between 0 and 1. The ratio of 0.01 means that each query covers 1% (or 0.01 times) of the dataset, allowing for focused analysis.
We present the recall, latency (in milliseconds), and RPS (requests per second) for various probability ranges while keeping the ef_search constant. The ef_search parameter represents the size of the list utilized during k-NN (k-Nearest Neighbors) searches, determining the trade-off between search accuracy and query processing time.
pgvecto.rs, when used with VBASE, consistently yields improved recall, particularly when working with low probability values.
Other features
pgvecto.rs 0.2 introduces the following key features and improvements other than VBASE integration:
-
FP16: Users can now store embeddings in PostgreSQL using half the float32 size, significantly improving latency. This optimization has a negligible impact on final recall, less than 1%.
-
Asynchronous indexing: Insertion operations are non-blocking, ensuring a smoother and more efficient data insertion and indexing process.
-
Doubled query performance: pgvecto.rs 0.2 offers query performance that is twice as fast as the previous version (0.1), marking a significant leap forward in system efficiency.
-
Observability: The new
pg_vector_index_statview provides a transparent view into the indexing internals of pgvecto.rs. Users can monitor index construction, configuration adjustments, and detailed statistical analysis in real time, fostering a more intuitive and controlled environment.
Quick start
To get started with pgvecto.rs 0.2, you could run it in a docker container:
Please check out our documentation for more details. We encourage you to try out pgvecto.rs, benchmark it against your workloads, and contribute your indexing innovations. Join our Discord community to connect with the developers and other users working to improve pgvecto.rs!