Akash DahadProduct engineer · India

pgvector vs LanceDB vs Turbopuffer: when each one makes sense

Opinion Vector search and RAG 6 min read
pgvectorLanceDBTurbopufferVector databases

We've kept our vectors in all three. What each one is, where it runs, how you pay, and the questions that should decide between them.

“Which vector database should we use?” usually hides two better questions. Where does the data have to live? And who is going to run it?

We’ve had our vectors in all three of these. pgvector first, then Turbopuffer, then LanceDB. Each was a reasonable answer to a different version of those two questions. Here is when I’d pick each one, based on what happened to us, not on anyone’s benchmark.

A quick definition first. A vector database stores embeddings, lists of numbers that capture what a piece of text means, and finds the ones closest to a question’s embedding.

The three at a glance

pgvectorTurbopufferLanceDB
What it isA Postgres extension that adds a vector type and similarity searchA hosted search service for vectors and full textAn open-source vector database that runs as a library inside your app
Where the data livesIn your Postgres tablesIn object storage, cached on SSD and in memoryIn Lance files on a disk or in object storage
Who runs itYou, or your Postgres hostTurbopufferYou
How you payFree and open source. You pay for the Postgres it runs inBy usage (storage, writes, queries), with a monthly minimum per planFree and open source. You pay for the disk and compute. A commercial Enterprise version is sold separately
Good atVectors next to the rest of your data, in one databaseLots of data with no servers to run. Vector and full-text searchRunning anywhere, including a customer’s cloud. Versioned data
Watch forThe index only helps one query shape. Filters run after the index scanFirst queries on cold data are slower. BYOC and single-tenant are enterprise-plan onlyYou own the writes, the backups and the index tuning
How it went for usSlowed as tenants grew, because our queries couldn’t use the indexRan in one region for us, so self-hosted customers had no AI searchAll our production tenants run on it. About 5 to 6 ms a query from 100k to 500k rows

pgvector: when vectors are a small part of a Postgres app

pgvector adds a vector column to Postgres and lets you sort rows by how close they are to a query vector. The big win is that vectors live next to everything else. You can join them to your other tables, filter with ordinary SQL, and keep them in the same transaction as the rows they describe. There is no second system to run.

By default it does exact search, which compares the question with every row and has perfect recall. For speed you add an approximate index, HNSW or IVFFlat, which trades a little recall for a lot of speed.

Two things to watch:

  • The index only helps one query shape. The query needs an ORDER BY on a distance operator, in ascending order, and a LIMIT. Wrap the distance in an expression and Postgres goes back to comparing against every row.
  • Filters run after the index scan. With an approximate index, a narrow filter can leave you with fewer results than you asked for. Since version 0.8.0, pgvector has iterative index scans, which keep scanning until enough rows pass the filter.

This is where we started, with pgvector tables in each tenant’s schema. The way our queries were written, the index couldn’t help, so each question was compared against every chunk the user could access. It was fine for small companies and slowed as customers grew into thousands of documents. Part of that was how we wrote the queries, not pgvector itself.

Pick it when you already run Postgres, your vector data is modest, and you’d rather have one database than two. Then run EXPLAIN on your real search query and check the index is used.

Turbopuffer: when you want someone else to run it

Turbopuffer is a hosted service. Your data sits in object storage, the cheap bucket storage every cloud sells. When you query it, the data gets cached on fast local disks and in memory, so the first query on cold data is much slower than the ones after it. It does vector search, full-text search and metadata filters. Each namespace is stored separately, which fits one namespace per tenant.

You pay by usage, for storage, writes and queries, with a monthly minimum that depends on the plan. Its docs list public regions on AWS, GCP and Azure. Single-tenant clusters and BYOC, bring your own cloud, are on the enterprise plan.

Turbopuffer was the first new store we moved to. We copied our existing vectors into it as they were, so the comparison was fair, and measured it against Postgres on retrieval quality before removing the old path.

The catch, for us, was where it ran. It ran in one cloud region, so a customer hosting BHyve in their own cloud would get no AI search at all. If you have customers like that, the enterprise plan with BYOC is the one to price.

Pick it when your data is allowed to live in a vendor’s cloud and you don’t want to run a stateful service yourself.

LanceDB: when the search has to go where the customer is

LanceDB is an embedded vector database. It runs as a library inside your program, like SQLite, and keeps its data as files in the Lance columnar format, on a local disk or in object storage. It supports vector search, full-text search and SQL filters, and keeps versions of your data. The open-source version is Apache-2.0 licensed, and the company also sells a commercial Enterprise version.

Because it’s just files, it runs wherever you can give it a disk. That’s why it fixed the problem the hosted store couldn’t: it can run in our cloud or in a customer’s, and we used it to move one enterprise customer’s search into its own cloud. All our production tenants run on it now. In load tests it searched in 5.3 ms at 100k rows and 6.2 ms at 500k, with memory flat near 1 GB, so query time no longer follows the size of the data.

The price is that you run it, and a store on a disk is state. That means one writer, a disk that outlives the pod, and snapshots to go back to. What that involves is in running a database on Kubernetes. You also own the index settings. Compressed indexes dropped recall@10 to 0.29 on our large tenants unless a refine step was added, which brings it back to 0.83 for about 8 ms. I wrote that up in the recall you lose to compressed vector indexes.

Pick it when search has to run inside a customer’s cloud, or anywhere you control the disk, and someone on the team is ready to own a stateful service.

My actual advice: don’t marry any of them

The decision that mattered most wasn’t which store. It was putting every store behind one interface, so the rest of the product never knows which one it’s talking to. Each tenant can run on LanceDB or Turbopuffer, in our cloud or theirs. Moving a tenant is a migration, not a rewrite. The full story of how we got there is in why we moved AI search from Postgres to LanceDB.

Questions that decide it

  • Must the data stay in a customer’s cloud? LanceDB, or a vendor’s BYOC plan. A hosted store in one region won’t do.
  • Are vectors a side feature of an app already on Postgres? Start with pgvector, and check the index is actually used.
  • Is nobody on the team going to own a stateful service? Use a hosted store like Turbopuffer.
  • Do you filter per user? Test filtered queries on their own. For us, per-user access filtering on LanceDB cost at most 37 ms in the worst case.
  • Do you compress the index? Measure recall against exact search, not just speed.

Whichever you pick, put it behind an interface and measure it on your own questions. The case study has all our numbers in one place.

Quick answers

Is pgvector good enough for production?
It can be, especially when vectors are a small part of an app that already runs on Postgres. Check that your queries can actually use its approximate index, and test how filtered queries behave.
What is Turbopuffer?
Turbopuffer is a hosted search service for vectors and full text. It keeps data in object storage, caches what gets queried on fast disks and in memory, and charges by usage.
Can I self-host LanceDB?
Yes. Open-source LanceDB is a library that runs inside your application and stores its data as files on a local disk or in object storage, so it runs wherever your app runs.
Does Turbopuffer offer bring your own cloud (BYOC)?
Yes, on its enterprise plan. Turbopuffer's docs list single-tenant clusters and BYOC deployments inside your own AWS, GCP or Azure account, arranged with their team.
The case study behind this post Moving AI search from Postgres to LanceDB 5–6 ms vector search