
pgvector-filterbench
A command-line tool for checking how pgvector search behaves once you add filters. It measures speed, compares approximate results with exact search, and checks query plans to see whether PostgreSQL is using your HNSW index.
About pgvector-filterbench
In an actual application, you usually need results from a particular customer, category or group of active records. Those filters can change how approximate vector search behaves. A query might finish quickly while missing some of the nearest matches that satisfy your conditions.
pgvector-filterbench runs an exact search as a reference, then tests different HNSW strategies and settings against it. You can compare how long each approach takes and how many of the exact search’s top matches it finds. That gives you something concrete to work with when adjusting the search parameters.
It also checks the query plans. PostgreSQL can choose a sequential scan, which makes a supposedly impressive HNSW result a little awkward: the index you thought you were testing wasn’t being used. The benchmark checks for that explicitly.
You can sample query vectors from your database or supply your own, then compare the standard HNSW search with strict and relaxed iterative scans. Results are written to JSON and Markdown. If you want to run it in CI, you can set thresholds so a drop in recall or unexpected index usage fails the check.
There’s a Docker demo with synthetic data if you want to see how it works before setting up a run against your own tables. The tool itself is written in Go, and prebuilt binaries are available.
The benchmark queries are read-only, although exact searches can still give the database a fair amount of work. For a larger dataset, I’d start on a replica or staging database and keep the initial test small.
Useful when you’re tuning filtered vector search and want to see what your settings actually change.
Release history
Version 0.1.2
Added
- Report how many rows every measured query returned:
rows_returned(mean and minimum) plusshort_result_runsin the JSON report, andRows (mean/min)plusShort Setscolumns in the Markdown report. Recall and same-rank alone cannot distinguish a filter-shortened result set from a complete but wrong one. The exact ground-truth row reports rows returned as well, which is alwaysk.exactfor eligible samples. - Optional
gate.require_full_resultscheck that fails the gate when any measured ANN configuration returns fewer thank.annrows. It is disabled by default, because short filtered-HNSW result sets are the condition the tool exists to measure.
Changed
- Raise the minimum supported Go version from 1.21 to 1.25 for patched dependencies.
Fixed
- Accept
--versionand-von the root command. Both previously failed withunknown flag: --version, and the version was absent from--help. The flag is wired after the embeddedVERSIONfile is loaded so it never reports thedevplaceholder, and it prints the same string as theversioncommand. - Avoid allocating unused per-run ANN row-count copies while building reports.
- Pin CI quality checks to Go 1.27.x and update Staticcheck and govulncheck to compatible
versions, fixing analyzer failures after the floating Go
stableversion advanced to 1.27. - Update
golang.org/x/textto v0.39.0 to fix GO-2026-5970, an infinite loop on invalid UTF-8 input in Unicode normalization, and update itsgolang.org/x/syncdependency.
External download
Version 0.1.1
Fixed
- Calculate recall against the exact top
k.annrows instead of every row returned by a largerk.exactquery. - Omit non-applicable
plan_validandindex_usedclaims from the exact JSON result row. - Run index validation and vector-dimension discovery in read-only transactions bounded by the configured statement and lock timeouts.
- Redact PostgreSQL server messages from logged and reported measurement errors while retaining operation context and SQLSTATE.
- Reject pgx simple-protocol connections, removing the runtime condition required by GO-2026-5004 without dropping Go 1.21 support.
- Build the container image with the patched Go 1.26.5 toolchain while continuing to test source compatibility with Go 1.21.
Added
- GitHub Actions checks for Go 1.21 compatibility, unit and race tests, vet, staticcheck, govulncheck, and PostgreSQL 16/17/18 pgvector end-to-end gates.
External download
Version 0.1.0
- Initial release of pgvector-filterbench.
- Go CLI with run and version commands.
- Four benchmark strategies: exact ground truth, bounded ANN, strict iterative scan, and relaxed iterative scan.
- Configurable sweep of hnsw.ef_search and hnsw.max_scan_tuples parameters.
- Seeded random sampling from the database for reproducible query vectors.
- External JSONL query-vector input for workload replay.
- Optional self-exclusion for corpus-derived queries, enabled in the sample configurations.
- Per-sample exact ground truth with index scans disabled in a read-only transaction.
- Read-only sampling and ANN transactions with bounded pool size and transaction-local statement/lock timeouts.
- EXPLAIN ANALYZE plan capture and validation: verifies an HNSW Index Scan on the expected schema, table, and index.
- PostgreSQL 18 JSON-plan compatibility for decimal Actual Rows values.
- Catalog validation for HNSW access method, opclass, table ownership, and valid/ready/live index state.
- Recall@k, same-rank, and latency statistics with configurable warmup and measured runs.
- Randomised strategy order and counterbalanced exact-first/ANN-first execution to reduce systematic cache bias.
- Deterministic ID tie-breaking and functional self-exclusion in exact and ANN queries.
- CI gate with meaningful failure on missing measurements, query errors, low recall, sequential scans, or absent index scans.
- Privacy-safe JSON and Markdown reports with neutral target labels, opt-in detailed evidence, configurable output formats, and enforced 0600 file permissions.
- Strict configuration validation and exact vector-dimension checks for external workloads.
- Focused tests for configuration, sampling, recall, gates, plan validation, reporting, version checks, and CLI exit codes.
- Go 1.21-compatible module graph and Docker build.
- Project .gitignore covering the local IDEA.md brief, reports, binaries, secrets, and IDE files.
- Version-selectable, ephemeral Docker Compose demo with pgvector and 10,000 distinct deterministic synthetic vectors at 100%, 10%, 1%, and 0.1% filter selectivity levels.
- Full Docker benchmark-gate verification on PostgreSQL 16.14, 17.10, and 18.4 with pgvector 0.8.5.
- PostgreSQL 18-compatible parent-directory data mount and TCP-only readiness check that avoids the initialization-server race.
- Apache-2.0 license.
External download

















