pg_pinecone Brings Compact, Filtered Vector Search Into Postgres
- Gate
- Machine Learning
- Departs
- Crew
- David Davis
- Passengers
- 322
Pinecone’s Apache 2.0 Postgres extension reports smaller indexes and faster searches than HNSW, with filtering applied during search.

Vector search inside Postgres can become costly as datasets grow, particularly when an application must find relevant records within a specific tenant, user, or category. Pinecone’s new open-source extension, pg_pinecone, targets both constraints: it adds an index designed to use less memory than HNSW and applies filters during search. The company reports faster unfiltered queries and higher recall on its filtered-search benchmarks, while keeping tables and SQL queries in Postgres.

Released on October 27, 2026, under the Apache 2.0 license, pg_pinecone is built on the search engine Pinecone runs at scale. Its default engine runs within Postgres and doesn’t require a Pinecone account, API key, or network connection. The extension also offers options to search through pgvector’s existing HNSW index or send searches to Pinecone’s managed service.
One extension, three search engines
Applications continue to connect to Postgres and issue familiar SQL. A vector query can still order rows by distance, such as ORDER BY embedding <=> $1 LIMIT 10. Tables and full vectors remain in Postgres, which stays the system of record.
Each table can use one of three engines: native, the default that builds and searches an index inside Postgres; pgvector, which uses an existing HNSW index; or remote, which searches an index in Pinecone’s managed service. Switching engines takes a call to pinecone.set_engine(), without changing application queries.

The native engine, like HNSW, uses approximate nearest-neighbor search. Its index organizes vectors into clusters using an inverted file index (IVF). Instead of storing full vectors and graph links, it stores compact, quantized RaBitQ codes—about one bit per dimension plus correction values. The codes sit together by cluster, allowing searches to read contiguous pages instead of following graph links. The quantization method is described by Gao and Long, SIGMOD 2024; comparisons with other quantization methods are available at VQ-Bench and in Pinecone’s account of how it was built.
Smaller indexes, staged scoring
HNSW stores a full copy of each vector alongside links to nearby vectors. Searches traverse that graph and compare full vectors, so keeping the index in memory can matter to performance. Pinecone’s approach trades that layout for cluster search and compressed codes. On one million 768-dimensional vectors, Pinecone reports a 136 MB native index, compared with 2.0 GB for HNSW on halfvec and 4.1 GB for HNSW on full-size vectors.

Search also proceeds in stages. First, the engine finds nearby cluster centroids. Then it estimates row distances from RaBitQ codes and keeps promising candidates. Finally, it reranks those candidates using the full vectors stored in the table. Most candidates can therefore be screened with bit operations before the more expensive full-vector comparisons.
At 0.95 recall, Pinecone reports 1.3 ms per query, compared with 1.7 ms for HNSW on halfvec and 2.7 ms on full-size vectors. At 0.99 recall, the respective times are 2.3 ms, 4.7 ms, and 6.7 ms.

Filtering happens inside the search
Filtered search is a particular weakness of post-filtering. With HNSW, the index finds nearest neighbors first and applies the SQL WHERE condition afterward. A narrow condition can discard most candidates, leaving fewer rows than the query’s LIMIT. Iterative scans can search further to fill the result list, but take more time; using relaxed_order can also affect accuracy.
The native engine checks filters during search and chooses a strategy based on how many rows match. By default, when 3% or fewer rows match, it pre-filters: it scans all matching rows across clusters and scores them using full vectors, producing exact results. For broader filters, it searches more of the nearest clusters—up to half—and checks the filter within each cluster before scoring.

In a test where 10% of rows matched, Pinecone reports 1.000 recall in 12.3 ms with the native engine. HNSW with iterative scans reached 0.920 recall in 5.9 ms. That’s a tradeoff in this reported case: the native search took longer while finding all of the measured relevant results.

New rows join their nearest cluster and become searchable immediately. Cluster centroids remain in their original positions, though. After substantial changes—such as a bulk load that doubles a table, or new data unlike the data used to build the index—Pinecone advises running REINDEX or enabling automatic maintenance to rebalance clusters.
What the benchmarks show
Pinecone compared the native engine with pgvector HNSW on one million 768-dimensional wiki_dpr vectors. The tests used an AWS r6id.4xlarge with 16 vCPUs and 128 GB RAM. Unfiltered latency, build time, and index size were measured in one PostgreSQL 17 session; filtered search used PostgreSQL 18; and a separate test imposed a 4 GB memory cap. Reported latency is median (p50), at k=10 and one client unless specified. The benchmark harness README provides setup details and commands for rerunning the tests.
For unfiltered searches at the same recall, the native engine’s measured latencies were 1.27 ms at 0.95 recall and 2.28 ms at 0.99 recall. HNSW on halfvec took 1.71 ms and 4.65 ms; HNSW on full-size vectors took 2.67 ms and 6.72 ms.

Table 1: Unfiltered search latency at the same recall (1M vectors, 768 dimensions)
For filtered queries designed so that the closest matches mostly fell outside the filter, the native engine returned 0.981 recall in 8.3 ms when 1% of rows matched, and 1.000 recall in 12.3 ms at 10%. HNSW on halfvec reached 0.924 recall in 56 ms for the 1% case and 0.922 recall in 5.1 ms for the 10% case. These results describe a demanding filter setup; they shouldn’t be read as a guarantee for every data distribution or query.

Table 2: Filtered search recall and latency (1% and 10% of rows matching)
Index construction took 45 seconds for pg_pinecone, versus 62 seconds for HNSW on halfvec and 79 seconds for HNSW on full-size vectors.

Table 3: Index build time (1M vectors, 768 dimensions)
The 136 MB native index is substantially smaller than the two HNSW indexes in these tests. That difference may matter where database memory is shared among indexes, queries, and other workloads. Pinecone also includes results for searches with memory capped at 4 GB in its memory-cap benchmark.

Table 4: Index size and search with memory capped at 4 GB
Optional services and a path to managed search
Teams can keep using the native engine as their data grows, then move search to Pinecone if a larger index strains database memory. With an API key, pinecone.set_engine('docs', 'remote') changes the table to the remote engine. Embeddings sync to a Pinecone index in the background, while searches continue in Postgres until the copy completes. Queries stay the same, and the engine can be switched back.
The extension also offers optional text embedding, full-text search, and reranking. Its embed() function calls Pinecone’s inference service to turn text into vectors; it works with native and remote search, and only the embedding call needs Pinecone. Pinecone says its free tier covers a first build.
For keyword search, Pinecone’s BM25 full-text search can operate on the same table as vector search. The extension’s track_docs() and search_docs() functions support queries for exact terms such as product names or error codes. The rerank() function reorders a shortlist with Pinecone reranking models, which can help when the top few results matter or when combining keyword and vector results.
Getting started and contributing
Install a prebuilt version from GitHub releases or use the pineconeteam/pg_pinecone Docker image. An existing vector column can be indexed, or a new one can be populated with embed() and a Pinecone API key. A basic setup creates a table with an embedding column, enables the extension, and creates an index with a filter column:
CREATE TABLE docs (
id bigint PRIMARY KEY,
tenant_id bigint,
body text,
embedding vector(768)
);
CREATE EXTENSION pg_pinecone;
SELECT pinecone.create_index('docs', 'embedding', filter_column => 'tenant_id');Queries can continue to filter by tenant and sort by vector distance:
SELECT id, body
FROM docs
WHERE tenant_id = $1
ORDER BY embedding <=> $2
LIMIT 10;Full instructions are in the README. Pinecone maintains the extension and reviews pull requests. For this first release, it says it will shape the public roadmap using feedback on GitHub, in Discord, and at monthly office hours. Developers can also submit a feature request, support an existing request, share benchmark results, or report a bug.
The practical case for pg_pinecone rests on whether its compact index and in-search filtering fit a team’s data and workload. Its published benchmarks offer a starting point; testing against a production dataset will show how those tradeoffs hold for a particular mix of filters, updates, and recall targets.