pgvectorscale

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

4posts · 30d
Nov 30 posts
  1. DEV · · @jamilxt

    pg_vectorsearch vs pgvector: The 42-Hour Vector Index Just Became a 100-Minute One If you have ever kicked off a pgvector HNSW index build on a large embedding table and watched the hours tick by, the announcement Tiger Data made on October 13 reads like a targeted attack on your pain. Their new open-source extension, pg_vectorsearch, introduces an index called PRISM. On the same 128 GiB machine where a pgvector HNSW build over 100 million embeddings never finished at all, PRISM finished in 1 hour 40 minutes. On a machine 4x more expensive, HNSW needed 42 hours to do what PRISM did in 100 minutes. That is the headline. The useful question is what sits underneath it, because "should I switch my vector index" is a decision with real migration cost, and the answer in October 2026 is more conditional than the launch post makes it sound. Here is the breakdown: what PRISM actually is, what the numbers do and do not prove, and a checklist for deciding whether your workload should touch it yet. One disclosure up front: pg_vectorsearch shipped as an alpha one day before this article, so nobody outside Tiger Data has production experience with it, including me. Everything below comes from Tiger Data's announcement, their public benchmark tooling, and independent writeups. I will mark clearly which numbers are vendor-reported. What was actually announced Tiger Data, the company behind TimescaleDB, released pg_vectorsearch as an open-source PostgreSQL extension under the PostgreSQL license. It adds a new index access method called PRISM, short for Partitioned Routing Index for Similarity Matching. Three facts matter more than the name: - It is a native Postgres index. Not a sidecar service, not a separate database. You create an index the way you create a GiST or HNSW index, and your existing tooling, backups, and replication keep working. - It indexes your existing pgvector columns. No table rewrite, no data copy. A table already using pgvector's vector or halfvec types can get a PRISM index, and Tiger Data says your pgvector queries run unchanged. - It requires PostgreSQL 18 or later. That alone is a blocker for a large share of production deployments still on 15 through 17. The positioning detail that got less attention: Tiger Data describes pg_vectorsearch as the successor to pgvectorscale, their earlier DiskANN-based extension, which is heading into maintenance mode. If you adopted pgvectorscale last year on the strength of its Pinecone-comparison benchmarks, the roadmap just moved under you. That is worth knowing before your next infrastructure planning cycle. How PRISM works, without the paper HNSW, the index inside pgvector that most teams use, builds a multi-layer graph. Every vector is a node, and a search hops from node to node, narrowing down toward the nearest neighbors. The problem at scale is not compute. It is memory. Graph hops are unpredictable in advance, so the CPU spends most of its time stalled waiting on RAM, and the index itself has to stay resident. For 100 million vectors, Tiger Data measured the HNSW index at roughly 180 GB. PRISM takes the older IVF idea and hardens it. It groups similar vectors into k-means partitions, then stores each partition as compressed RaBitQ codes at roughly one bit per dimension, packed into whole database pages. A query finds the nearest few partitions and scans them sequentially. Sequential scans keep the CPU prefetcher busy and let SIMD instructions score many compressed vectors per instruction. Instead of a random-access graph walk, you get streaming passes over tightly packed pages. The result shows up in the storage number: 25 GB for the PRISM index versus 180 GB for HNSW on the same 100 million vectors. A 7x smaller index is what buys the cheap build and the small-machine query performance. The numbers, with their labels attached All figures below are from Tiger Data's launch benchmarks on 100 million Cohere embeddings, measured with their public benchmark tool, rekall, at recall@10 against exact brute-force results. They are vendor-reported, and every HNSW comparison used pgvector's halfvec type. - Build time at 100M vectors: HNSW could not finish building on a 128 GiB machine. On a 512 GiB machine, the build took 42 hours. PRISM built in 1 hour 40 minutes on the 128 GiB machine. - Query latency at 100M vectors: PRISM served 95% recall at a 6 ms median on the 128 GiB machine, versus HNSW's 8 ms on the machine with 4x the memory. - Index size: 25 GB for PRISM versus about 180 GB for HNSW. - Small scale holds up too: at 1 million vectors, PRISM served 99% recall in 15 ms on a 2 GiB machine. HNSW on a 4 GiB machine, twice the memory, took a reported 392 ms, and its build on that small box took about 21.7 hours while thrashing. Independent writeups of the announcement flagged the gaps fairly: the post does not state the embedding dimensionality of the test set, gives no throughput numbers, and contains no direct comparison against IVFFlat. Multi-client throughput testing is listed as still pending. None of that makes the numbers wrong, but it means the comparison you actually care about, PRISM versus whatever your workload does today on your hardware, does not exist yet. Run the rekall tool on your own data before believing any of this for your case. The alpha fine print is not small Tiger Data is unusually blunt about the state of the release, and the release notes deserve to be quoted in spirit: alpha quality, meant for testing, not production. Specifically: - Heavy churn needs a manual rebalance. If your table gets constant inserts, partition quality degrades until you intervene by hand. - Deletes do not reuse space yet. A delete-heavy workload will bloat the index with no built-in recovery. - Filtered search is on the GA roadmap, not in the alpha. If your RAG pipeline filters by tenant ID, date, or access control before similarity ranking, the alpha cannot do that efficiently. - Indexes should be recreated between prereleases. Whatever you build today is disposable. That last cluster of caveats points at the same conclusion: PRISM is for evaluation and read-mostly workloads right now, not for your production embedding table with daily churn. Should you switch? A decision checklist The interesting part of this launch is not "PRISM beats HNSW." It is that the threshold where teams felt forced to leave Postgres for a dedicated vector database just moved again. Save this checklist: - Under ~1 million vectors: stay on plain pgvector with HNSW. It works, it is boring, and PRISM's advantages are smallest exactly where your problem is easiest. This is most RAG projects, most internal search tools, most prototypes. - 1M to ~50M vectors, existing HNSW builds completing in acceptable time: stay put, but benchmark PRISM in staging. If your HNSW index no longer fits comfortably in memory and your bill is driven by RAM, PRISM's 7x smaller footprint is a direct cost argument. - 50M+ vectors, or HNSW builds that take days or fail: this is the audience the announcement was written for. Test PRISM now, on Postgres 18, in a non-production environment, with the rekall benchmark on your own embeddings. - Heavy insert/update churn or frequent deletes: wait for GA. The alpha's rebalance and space-reuse gaps hit exactly this pattern. - Filtering-heavy queries (tenant scoping, metadata filters): wait for GA. Filtered streaming search is on the roadmap, not shipped. - Currently on a dedicated vector DB (Pinecone, Qdrant, Weaviate) mainly for scale: this announcement is your quarterly reminder to re-run the stay-on-Postgres math. The direction of travel for two years has been Postgres absorbing the workloads that justified those services. - On Postgres 17 or earlier: the extension requires Postgres 18, so your first milestone is an upgrade, not an index change. The bigger story: the vector database market keeps shrinking Step back from the benchmark and look at the sequence. In 2023, running RAG meant standing up a dedicated vector database. Then pgvector made small-scale vector search a one-line extension install. Then pgvectorscale pushed Postgres into the tens of millions of vectors. Now PRISM is claiming the 100 million range on hardware a fraction of the cost, with no second system to operate, secure, back up, or keep consistent with your relational data. For a certain class of workload, the "we need a vector database" conversation is ending the same way the "we need a cache server" and "we need a search cluster" conversations ended for many teams: with a Postgres feature. Every team that chose a dedicated vector DB for scale reasons rather than feature reasons should keep a running estimate of what it would cost to move back, because the answer changes every quarter, and lately it changes in Postgres's favor. What I would actually do If I were planning a vector workload today: start every new project on plain pgvector regardless of expected size, because the exit cost from Postgres is low and the entry cost of a dedicated service is permanent. Revisit at the first sign of memory pressure, and at that point evaluate pgvectorscale's StreamingDiskANN for current production needs and PRISM for the 100M+ future, with the understanding that one is production-hardened and the other is a 48-hour-old alpha. And before any switch, generate your own numbers with rekall, because the only benchmark that matters is the one run on your embeddings, your hardware, and your recall target. I write about databases, AI infrastructure, and backend engineering every week. Subscribe, it is free, and it helps more than you know. Have you hit the ceiling of HNSW on a real workload? I am curious how long your largest index build took and whether it pushed you to a dedicated vector database or you stayed on Postgres. Tell me in the comments. Sources: Tiger Data's October 13 announcement (TimescaleDB on X), the pgvectorscale repository for the maintenance-mode note, and independent coverage of the launch benchmarks.

    2 reactions
  2. X · · @0x15f

    THE TUPLES ARE LEAKIN 🫤 pgvectorscale#276

    2 likes · 239 views
  3. DEV · · @fabwaseem

    pgvector vs Pinecone vs Qdrant: Benchmarked for RAG in 2026 I loaded the same 100,000 OpenAI embeddings into pgvector and Qdrant and measured recall, latency, index build and filtered search. Pinecone is covered from its docs only, since I didn't run it. The original, with any updates, lives on fabwaseem.com. pgvector is a PostgreSQL extension that stores embeddings in a vector column and searches them with HNSW or IVFFlat indexes, next to your normal tables. Qdrant is an open-source vector database you run yourself or use as a managed cloud. Pinecone is a fully managed, serverless vector database you only reach through an API. For a RAG app, the real question is whether you need a separate vector database at all. I loaded the same 100,000 OpenAI embeddings (1,536 dimensions) into pgvector 0.8.7 on PostgreSQL 18.6 and into Qdrant 1.19.2 on one machine. Then I measured recall, latency, build time and filtered search. Pinecone is covered from its official docs and limits only, because I didn't run it and I won't invent numbers for it. TL;DR: pgvector vs Pinecone vs Qdrant, which should I use? Start with pgvector if you already run Postgres and have up to a few million vectors. One database, SQL joins, transactions and backups you already have. Choose Qdrant when vector search is the core workload and you need the best recall per millisecond or heavy filtering. Choose Pinecone when you want zero infrastructure and accept a managed service with usage pricing. | | pgvector | Qdrant | Pinecone | | --- | --- | --- | --- | | What it is | Postgres extension | Vector database (open source) | Managed vector database (closed) | | Hosting | Anywhere Postgres runs | Self-host or Qdrant Cloud | Pinecone's cloud only | | Index | HNSW, IVFFlat | HNSW per segment | Managed (serverless, object storage) | | Max indexed dims | 2,000 vector, 4,000 halfvec | 1,536 tested here | 20,000 dense | | Filtering | SQL WHERE (post-filter, iterative scans) | Payload indexes + filter-aware HNSW | Metadata filters (40 KB per record) | | Consistency | Transactional (ACID) | Upserts readable after wait=true | Eventually consistent | | Recall@10 at ~2.6 ms, my test | 0.978 (ef_search 100) | 0.985 (hnsw_ef 40) | not tested | | Cost to start | Your Postgres | Free binary / free cloud tier | Free Starter; Standard $50/month minimum | Do I need a vector database for RAG? Usually not at first. If your app already uses PostgreSQL, pgvector adds vector search without a second system to deploy, secure, back up and keep in sync. In my test it answered top-10 queries over 100,000 OpenAI embeddings in 1.5-4 ms, with 95-99% recall. A dedicated database starts to pay off at very large scale, under heavy filtering, or when search load needs to scale separately. The hidden cost of a separate vector store is synchronisation. Every document insert, update and delete has to reach two systems, and a failed write leaves them disagreeing. With pgvector the embedding sits in the same row and the same transaction as the document it describes. What is pgvector? pgvector is an open-source PostgreSQL extension that adds vector, halfvec, bit and sparsevec types, distance operators like <=> (cosine) and <-> (L2), and approximate HNSW and IVFFlat indexes. Per the pgvector README, it "performs exact nearest neighbor search, which provides perfect recall" by default. An index trades a little recall for speed. CREATE EXTENSION vector; CREATE TABLE documents ( id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, tenant_id int NOT NULL, content text NOT NULL, embedding vector(1536) NOT NULL ); CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops); -- top 5 chunks for a question, inside one tenant SELECT id, content FROM documents WHERE tenant_id = $1 ORDER BY embedding <=> $2 LIMIT 5; Index limits matter for model choice. HNSW can index a vector of "up to 2,000 dimensions" and a halfvec of "up to 4,000 dimensions". A 3,072-dimension model such as text-embedding-3-large needs a halfvec index or a shorter output size. What are Qdrant and Pinecone? Qdrant is an open-source vector search engine written in Rust. It stores points (vectors plus a JSON payload), builds an HNSW index per segment, and adds payload indexes so filters run inside the graph search. You can run a single binary, Docker or Qdrant Cloud. Pinecone is a managed, serverless vector database. Per its architecture docs, "all your vector data is stored in highly efficient, distributed object storage." Pinecone "separates write and read operations into different paths, with each scaling independently based on demand." There is no self-hosted version. How I benchmarked pgvector and Qdrant 1. Data. The first 100,000 rows of the public DBpedia OpenAI embeddings dataset: 1,536-dimension text-embedding-ada-002 vectors of Wikipedia entities, a typical RAG shape. 1,000 held-out rows from the same dataset served as queries. 2. Ground truth. Exact cosine top-10 for every query, computed with NumPy. Recall@10 is the share of those 10 that each engine returned. 3. Machine. One 8-vCPU, 15 GB Linux box, everything on localhost, no Docker. 4. pgvector. PostgreSQL 18.6 with pgvector 0.8.7, shared_buffers = 2GB, maintenance_work_mem = 2GB. HNSW with defaults (m = 16, ef_construction = 64), loaded with binary COPY through psycopg 3. 5. Qdrant. The Qdrant 1.19.2 release binary, cosine distance, m = 16 and ef_construct = 64 to match pgvector, default optimizer settings (it made 4 segments). Loaded with the official Python client over gRPC from a single process. 6. Queries. One client, sequential, 50 warm-up queries, then 1,000 timed queries. Latency includes the Python client round trip on both sides. 7. Filters. Every vector got a random category from 0 to 9, about 10% of rows each. Filtered queries asked for the top 10 inside one category. Is pgvector fast enough? Recall and latency results Yes, at this scale both engines are fast. pgvector reached 0.948 recall@10 at 1.45 ms median with default settings, and 0.988 at 4.0 ms with hnsw.ef_search = 200. Qdrant reached 0.985 recall at 2.6 ms median and 0.999 at 5.4 ms. At roughly equal recall (about 98.5-98.8%), Qdrant was about 1.5 times faster: 2.6 ms against 4.0 ms. !pgvector vs Qdrant recall@10 vs median latency on 100,000 OpenAI embeddings: Qdrant 0.985 at 2.6 ms, pgvector 0.978 at 2.6 ms and 0.988 at 4.0 ms | Engine and setting | Recall@10 | p50 latency | p95 latency | Queries/s (1 client) | | --- | --- | --- | --- | --- | | pgvector, ef_search = 40 (default) | 0.948 | 1.45 ms | 2.16 ms | 683 | | pgvector, ef_search = 100 | 0.978 | 2.60 ms | 3.70 ms | 389 | | pgvector, ef_search = 200 | 0.988 | 4.02 ms | 5.82 ms | 249 | | pgvector halfvec index, ef_search = 100 | 0.973 | 2.33 ms | 3.30 ms | 433 | | Qdrant, hnsw_ef = 40 | 0.985 | 2.63 ms | 3.56 ms | 368 | | Qdrant, hnsw_ef = 100 | 0.997 | 3.73 ms | 4.66 ms | 255 | | Qdrant, hnsw_ef = 200 | 0.999 | 5.37 ms | 6.99 ms | 176 | | pgvector exact (no index) | 1.000 | 380 ms | 445 ms | 3 | | Qdrant exact (no index) | 1.000 | 24.7 ms | 32.6 ms | 39 | Why does Qdrant get higher recall at the same ef? It splits the collection into segments (4 here) and searches each one with that ef, so it explores more candidates in total. Compare the engines at equal recall, not equal settings. How fast do they load and index? Qdrant indexed faster: 30.8 seconds from the first upload to a fully indexed collection, with the upload itself taking 20.2 s from one Python process. pgvector loaded the rows with COPY in 3.9 s, then needed 69.1 s to build the HNSW index with the default 2 parallel workers. | | pgvector | Qdrant | | --- | --- | --- | | Load 100k vectors | 3.9 s (COPY) | 20.2 s (Python client, gRPC) | | Build HNSW index | 69.1 s | included, indexed at 30.8 s | | Table / data size | 798 MB | — | | HNSW index size | 781 MB (vector), 391 MB (halfvec) | — | | Server memory after test | Postgres buffers + OS cache | 1,293 MB RSS | Use the halfvec trick in pgvector: indexing embedding::halfvec(1536) halved the index from 781 MB to 391 MB and cost about half a point of recall (0.973 against 0.978 at ef_search = 100). Query the index with the same cast: CREATE INDEX ON documents USING hnsw ((embedding::halfvec(1536)) halfvec_cosine_ops); SELECT id FROM documents ORDER BY embedding::halfvec(1536) <=> $1::halfvec(1536) LIMIT 10; How does filtered vector search compare? Qdrant handled filters best. With a payload index on category, filtered top-10 queries returned 0.993 recall at 2.1 ms median. pgvector gave three very different results depending on the plan Postgres picked, so you need to know how its filtering works. | Filtered query (10% of rows match) | Rows returned (of 10) | Recall@10 | p50 | | --- | --- | --- | --- | | pgvector, planner's choice (B-tree on category, exact sort) | 10 | 1.000 | 44.2 ms | | pgvector, HNSW, iterative_scan = off | 3.92 | 0.389 | 1.77 ms | | pgvector, HNSW, iterative_scan = strict_order | 10 | 0.915 | 3.62 ms | | pgvector, HNSW, iterative_scan = relaxed_order | 10 | 0.953 | 3.37 ms | | Qdrant, payload index | 10 | 0.993 | 2.11 ms | Why does pgvector return fewer rows with a filter? Because HNSW filters after the index scan. The README explains: "If a condition matches 10% of rows, with HNSW and the default hnsw.ef_search of 40, only 4 rows will match on average." I measured 3.92. Since pgvector 0.8.0, iterative index scans keep walking the graph until enough rows match. -- once per session or per transaction (SET LOCAL) SET hnsw.iterative_scan = relaxed_order; SELECT id, content FROM documents WHERE tenant_id = $1 ORDER BY embedding <=> $2 LIMIT 10; Postgres often picks the exact plan by itself for a selective filter. In my test it used the category B-tree and sorted about 10,000 rows exactly: perfect recall, but 44 ms instead of about 3 ms. That is fine for one tenant with a few thousand chunks. For large tenants, check EXPLAIN and turn on iterative scans. If one filter dominates, consider a partial index or partitioning by tenant. What does Pinecone offer that pgvector and Qdrant don't? Fully managed, serverless scaling with nothing to run. Reads and writes scale separately, storage lives in object storage, and you never tune ef or m. The trade-offs are documented: - Eventual consistency. The known limitations page says "Pinecone is eventually consistent, so there can be a slight delay before upserted records are available to query." - Operation limits. Per the operation limits: dense vectors up to 20,000 dimensions, 40 KB of filterable metadata per record, 1,000 records or 2 MB per upsert batch, and top_k up to 10,000. - Plans. The object limits give the free Starter plan 2 GB of serverless storage and 5 indexes per project, all in AWS us-east-1. Pinecone pricing lists the Standard plan at a $50/month minimum. - Network hop. Every query leaves your VPC. Expect your cloud region's round-trip time on top of search time. My localhost latencies are not comparable to Pinecone and I did not measure it. When should I choose each one? Decide by what you already run and what dominates your workload. The pgvector default is strong for product teams. Move when you measure a reason, not before. !Decision guide: choose pgvector if you already run Postgres, Qdrant when search is the product, Pinecone for zero infrastructure 1. Choose pgvector when your data lives in Postgres, you need joins, row-level security or transactions with your embeddings, and you have up to a few million vectors per index. Add pgvectorscale (StreamingDiskANN) if the index outgrows RAM. 2. Choose Qdrant when search is the product: tens of millions of vectors, many filters, multi-vector or hybrid search, or quantization to cut memory. Its quantization guide says scalar quantization achieves "4x compression with minimal accuracy loss." 3. Choose Pinecone when nobody on the team should run a database, traffic is spiky, and a usage bill plus eventual consistency are acceptable. How do I move from pgvector to Qdrant later? Keep embeddings and IDs portable from day one. Use the same primary key in both systems, store the embedding model name and dimensions with each row, and write a re-sync job that streams rows by ID. Qdrant accepts integer or UUID point IDs, so a UUIDv7 primary key maps across directly. Then run both side by side, compare recall on a fixed set of real queries, and switch reads before you stop writing to Postgres. Common mistakes with vector search in production - Indexing 3,072-dimension vectors as vector. HNSW on vector stops at 2,000 dimensions. Use halfvec or a smaller output dimension. - Forgetting iterative scans. Filtered HNSW queries in pgvector can silently return fewer than LIMIT rows. - Comparing engines at equal settings. ef means different work in different engines. Compare at equal recall. - Measuring recall on random vectors. Use real embeddings from your model. Random data hides graph quality. - Creating Qdrant payload indexes after loading. The indexing docs say payload indexes should be created before ingesting data, so filter-aware HNSW edges get built. - Ignoring re-embedding cost. Switching embedding models means re-embedding everything, whichever store you use. If you want a working starting point, my open-source Next.js AI starter kit, Forgekit, ships RAG on pgvector. For self-hosting Postgres or Qdrant next to your app, see self-hosting Next.js with Coolify. Key takeaways - With 100,000 OpenAI embeddings, pgvector 0.8.7 hit 0.948 recall@10 at 1.45 ms with defaults and 0.988 at 4.0 ms with ef_search 200. - Qdrant 1.19.2 hit 0.985 recall at 2.6 ms, about 1.5x faster than pgvector at roughly equal recall. - pgvector's HNSW filters after scanning: a 10% filter returned only 3.92 of 10 rows until iterative scans were enabled. - Qdrant's payload index gave the best filtered search in my test: 0.993 recall at 2.1 ms. - A halfvec HNSW index halved pgvector's index size (781 MB to 391 MB) for about half a point of recall. - Pinecone is serverless and eventually consistent, supports 20,000-dimension vectors, and its Standard plan has a $50/month minimum. - Start with pgvector if you already run Postgres; move to Qdrant or Pinecone when measurements show a need. FAQ Is pgvector as good as Pinecone or Qdrant? For most RAG apps up to a few million vectors, yes. In my test of 100,000 OpenAI embeddings, pgvector reached 0.988 recall@10 at 4.0 ms median, and Qdrant reached 0.985 at 2.6 ms. Qdrant was about 1.5 times faster at equal recall and better at filtered search, but pgvector keeps embeddings in the same transactional database as your data. Do I need a vector database for RAG? Not usually at the start. If your app already uses PostgreSQL, the pgvector extension adds vector columns and HNSW indexes without a second system to deploy, back up and keep in sync. Consider a dedicated vector database when you reach tens of millions of vectors, need heavy filtering at low latency, or need to scale search separately. Why does pgvector return fewer results than my LIMIT? Because pgvector's HNSW index applies WHERE filters after scanning the index. With a filter matching 10 percent of rows and the default ef_search of 40, about 4 rows match on average; I measured 3.92. Set hnsw.iterative_scan to relaxed_order or strict_order, available since pgvector 0.8.0, so the scan continues until enough rows match. How many dimensions can pgvector index? pgvector's HNSW and IVFFlat indexes support the vector type up to 2,000 dimensions, halfvec up to 4,000 and bit up to 64,000. For a 3,072-dimension model such as text-embedding-3-large, index the column as halfvec or request a smaller output dimension. Pinecone supports dense vectors up to 20,000 dimensions. Is Qdrant faster than pgvector? In my single-machine test, yes, at equal recall. Qdrant 1.19.2 returned 0.985 recall@10 at 2.6 ms median against pgvector's 0.988 at 4.0 ms, and indexed 100,000 vectors in about 31 seconds against pgvector's 69-second HNSW build. With default settings, pgvector was faster per query but at lower recall, 0.948 at 1.45 ms. How much does Pinecone cost? Pinecone has a free Starter plan with 2 GB of serverless storage and up to 5 indexes per project, all in AWS us-east-1. Its Standard plan for production has a $50 per month minimum, after which you pay as you go for usage, according to Pinecone's pricing page. Qdrant's open-source build and pgvector are free to self-host. What is halfvec in pgvector? halfvec is pgvector's half-precision vector type, storing each dimension in 2 bytes instead of 4. Indexing an expression like embedding::halfvec(1536) halves the HNSW index size; in my test it shrank from 781 MB to 391 MB with recall dropping from 0.978 to 0.973. It also raises the indexable limit to 4,000 dimensions. Is Pinecone eventually consistent? Yes. Pinecone's documentation states that it is eventually consistent, so there can be a slight delay before upserted records can be queried, and suggests checking index stats to confirm counts. pgvector writes are transactional and visible on commit, and Qdrant upserts sent with wait=true are applied before the call returns. --- Originally published on fabwaseem.com.

    2 comments
  4. pg_vectorsearch Claims 6 ms at 100M Vectors. Filtered Queries Can Come Back Short - Book: Database Playbook - Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go - My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools - Me: xgabriel.com | GitHub --- If your RAG app keeps its embeddings in Postgres, the index behind it is probably pgvector's HNSW. pgvector's own README says HNSW "has slower build times and uses more memory" than its other index type, IVFFlat, in exchange for a better speed-recall trade-off. On October 13, Tiger Data, the company behind TimescaleDB, announced pg_vectorsearch, an open-source Postgres extension with a new index called PRISM. Its headline: 6 ms median latency at 95% recall on 100 million vectors, on a machine where pgvector's HNSW build did not finish. On October 14 it drew a Hacker News thread. Two things decide whether this matters to you yet. The numbers come from Tiger Data's own benchmark. And the alpha has a gap right where most RAG queries live: the WHERE clause. What Tiger Data shipped PRISM stands for Partitioned Routing Index for Similarity Matching, and it is a native Postgres index access method, so there is no separate service to run. Instead of HNSW's graph, it groups vectors into k-means clusters and, per the announcement, "stores each vector as a RaBitQ code of roughly one bit per dimension." A query walks a centroid tree to the nearest clusters, scans their posting lists, filters candidates with RaBitQ error bounds, then reranks them with full-precision vectors from the table (README). The README describes it as "conceptually similar" to pgvector's IVFFlat. The practical details, all from the README: - It needs PostgreSQL 18 or later. - It ships its own vec32 and vec16 types, and they are binary-compatible with pgvector's vector and halfvec. - It can index an existing pgvector column without rewriting the table, and the two extensions can sit side by side. - It is under the PostgreSQL License. The pitch is one sentence in the announcement: "We built pg_vectorsearch so you can stay in PostgreSQL." The numbers are Tiger Data's, so read the conditions Every result in Tiger Data's announcement comes from its public benchmark tool, rekall. Recall is recall@10 against exact brute-force results, and every HNSW run used pgvector's halfvec. Here is the 100-million-vector run, on Cohere embeddings, as the post reports it: | Machine | Index | Build | Size | p50 @95% | p50 @99% | |---|---|---|---|---|---| | r8i.4xlarge (128 GB) | PRISM | 1 h 40 min | 25 GB | 6 ms | 21 ms | | r8i.4xlarge (128 GB) | HNSW | did not finish | n/a | n/a | n/a | | r8i.16xlarge (512 GB) | PRISM | 49 min | 25 GB | 4 ms | 19 ms | | r8i.16xlarge (512 GB) | HNSW | 42 h | 180 GB | 8 ms | not reached | At 1 million vectors, the same post reports PRISM at 15 ms median for 99% recall on a 2 GB c8g.medium, against 392 ms for HNSW on a 4 GB c8g.large. It says the HNSW build on the 4 GB machine took about 21.7 hours and thrashed. What the announcement doesn't give you: the dimensionality of either dataset, throughput (queries per second), or a direct IVFFlat comparison. Multi-client throughput testing is listed as still pending. In the HN thread, one commenter asked for exactly that: "qps and precision/recall, please." I haven't run pg_vectorsearch myself, so treat the table as the vendor's claim, which rekall lets you check on your own data. What the alpha doesn't do yet Tiger Data is upfront about this. "This is the first public release of pg_vectorsearch, and we're calling it an alpha," the announcement says, and the 0.1.0-rc1 release notes call it "alpha quality and meant for testing, not production." The known issues in those notes are the part to read before you plan anything: - Filtered queries can return fewer rows than LIMIT. If the rows that pass your WHERE aren't among the candidates the scan ranked, it doesn't look further (issue #188). A multi-tenant query like WHERE tenant_id = 7 ... LIMIT 10 can come back with fewer than 10 rows. - Large ordered scans can return partial results without an error. With no LIMIT, or a LIMIT larger than work_mem lets it rank, you get only what that budget covers. Raising work_mem fixes the budget case. - At most 1,968 dimensions, and no unlogged tables or expression indexes. - Upgrades between prereleases may not work, so plan to drop and recreate the extension and its indexes. The announcement adds the rest. There is no automatic rebalancing, so recall can drift under heavy churn until you run prism_rebalance or REINDEX. Space from deleted rows isn't reclaimed until REINDEX, and replication and backup/restore testing is still pending. Filtered "streaming search" is planned for GA. The dimension cap is the one to check first. OpenAI's text-embedding-3-large returns 3,072 dimensions by default (OpenAI docs), and pgvector's HNSW can index halfvec up to 4,000 (pgvector README). If that's your setup, you'd need to shorten the vectors before PRISM could index them: re-embed with OpenAI's dimensions parameter, or truncate the stored vectors and re-normalize, which OpenAI's guide also describes. pgvectorscale moves to maintenance mode If you adopted Tiger Data's earlier extension, pgvectorscale, this is the news for you. Tiger Data's announcement says it is stable and runs production workloads, but will enter maintenance mode, and that its DiskANN-inspired graph index could lose recall on low-dimensional datasets. A pgvectorscale author said the same in the HN thread. The post doesn't say what pgvectorscale users should do next. As of October 14, the pgvectorscale README carries no maintenance notice, and Tiger Cloud's extension list still includes it. The announcement doesn't mention Tiger Cloud support for pg_vectorsearch, and a commenter in the HN thread noted it isn't on managed providers' extension lists yet. Try it next to HNSW, on a copy You need Postgres 18 for this anyway, so do it on a staging copy of the table, not your production database. The README shows indexing an existing pgvector column directly. Pick the operator class that matches your column type and distance: vec32_* for vector, vec16_* for halfvec, with _l2_ops, _ip_ops or _cosine_ops. CREATE EXTENSION pg_vectorsearch; CREATE INDEX documents_embedding_prism ON documents USING prism (embedding vec32_cosine_ops); -- 40 is the README's example value. -- 0 = auto (~0.95 recall); raise for recall, -- lower for speed. SET prism.nprobe = 40; On the copy, drop the HNSW index so the planner can only pick PRISM, then confirm it does: EXPLAIN SELECT id FROM documents ORDER BY embedding <=> ( SELECT embedding FROM documents WHERE id = 1 ) LIMIT 10; For recall, run the same query with index scans off, which gives you the exact top 10, and compare the two lists of IDs: BEGIN; SET LOCAL enable_indexscan = off; SET LOCAL enable_indexonlyscan = off; SELECT id FROM documents ORDER BY embedding <=> ( SELECT embedding FROM documents WHERE id = 1 ) LIMIT 10; ROLLBACK; Do that for a few hundred real queries, including your filtered ones, before you trust a number. Short results on filtered queries are issue #188, not your setup. So, would you switch? Vectors that fit in RAM, with HNSW fast enough? The alpha gives you little reason to move today. If your HNSW builds take a day, or your index no longer fits in memory, it is worth a weekend on a copy. Selective WHERE filters, like a per-tenant query, are where the alpha comes back short, so those are the queries to watch when GA lands. What's stopping you: the Postgres 18 upgrade, the filtering gap, or your managed provider's extension list? --- If this was useful Picking between HNSW, IVFFlat and a new index type is the same call as picking a store: you trade memory, build time and query shape against each other, and the benchmark only tells you about someone else's data. The Database Playbook walks through those trade-offs for Postgres, SQLite, Redis, DynamoDB and the rest, so you can make that call for your own system. I also build Hermes IDE (GitHub), free and source-available for macOS, Windows and Linux, where each coding-agent task can run on its own branch and worktree. That helps if you hand an experiment like this one to an agent. It's my project, so weigh that. ![Database Playbook: Choosing the Right Store for Every System You Build](amazon.com)

    1 comment

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

Scan pending.

README badges

Embed a badge in your README or website.

Live mentions · last 30 days
timescale/pgvectorscale mentions in the last 30 days