Extensions
Documentation
- quickstart
- PostgreSQL 17 Collection Quickstart
- hnsw_storage_contract
- HNSW Storage Mutation Contract
- benchmark_methodology
- Benchmark Methodology
- multi_tenancy
- Multi-Tenancy Runbook
- release_notes
- Release Notes
- troubleshooting
- Troubleshooting and Maintenance Runbook
- configuration
- Configuration
- SECURITY
- Security Policy
- pgcontext-vs-pgvector-vs-qdrant
- pgContext vs. pgvector vs. Qdrant
- release_matrix
- Release Gate Matrix
- security_review
- Security Review
- parity_matrix
- pgvector and Qdrant Parity Matrix
- README
- Release Tooling
- unsafe_ffi_audit_2026-07-11
- Unsafe and FFI Open-Source Readiness Audit
- AGENTS
- AGENTS.md — installing & using pgContext with an AI agent
- filters
- Filters
- README
- pgContext vs. pgvector vs. Qdrant benchmark harness
- support_policy
- Support, Version, Upgrade, and Deprecation Policy
- vector_search
- Dense Vectors and Exact Search
- release_process
- Release Process
- quickstart
- Quickstart
- installation
- Installation
- sql_object_inventory
- Installed SQL Object And Option Inventory
- README
- Heavy Test Harness
- feature_request
- feature_request
- client_examples
- Client-Facing Examples
- security
- Security Model
- bug_report
- bug_report
- hnsw_callback_contract
- HNSW Callback Boundary Contract
- repository_map
- Repository Map
- PULL_REQUEST_TEMPLATE
- PULL_REQUEST_TEMPLATE
- fuzzing
- Fuzzing
- testing
- Testing
- rollback
- Rollback and Repair Plan
- errors
- Error Categories And SQLSTATEs
- indexes
- Indexes
- postgres_module_organization
- PostgreSQL Integration Module Organization
- metric_operator_matrix
- Exact Metric and Operator Matrix
- README
- pgContext User Guide
- release_notes
- pgContext 0.1.0 — Vector and Hybrid Retrieval for PostgreSQL
- limitations
- Known Limitations
- pgvector_coexist
- Trying pgContext on an Existing pgvector Database
- pgcontext-vs-pgvector
- pgContext vs pgvector — GloVe-100-angular benchmark
- collections
- Collections
- vector_engine
- Vector Engine Architecture
- metric_kernels
- metric_kernels
- serving_memory_decision
- Serving-Memory Model Decision (2026-07-16)
- smoke-targets
- smoke-targets
- build_profile_2026-07
- HNSW Build Phase Profile
- playground
- Playground
- ARTIFACT_POLICY
- V1 Artifact Verification Policy
- metric_semantics
- Metric Semantics
- storage
- Rebuildable Storage Artifacts
- architecture
- Architecture
- known_issues
- Known Issues and Fit
- scripts
- Scripts and Generated Contracts
- README
- pgContext Playground
- index
- pgContext Documentation
- pgvector_migration
- Migrating from pgvector
- roadmap
- pgContext Product Roadmap
- hybrid_retrieval
- Hybrid Retrieval
- pgvector
- pgContext vs. pgvector vs. Qdrant benchmark
- CONTRIBUTING
- Contributing to pgContext
- storage_memory
- Storage and Memory
- CODE_OF_CONDUCT
- Code of Conduct
- bitvec
- bitvec
- README
- pgContext Contributor Guide
- release_gates
- Release Gates
- unsafe_review
- Unsafe Review
- pgcontext-vs-pgvector-vs-qdrant
- pgContext vs pgvector vs Qdrant — GloVe-100-angular benchmark
- roadmap
- Roadmap
- api_reference
- SQL API Contract
- operations
- Operations and Support
README
Contents

pgContext

A full AI search engine, built into Postgres.
Hybrid dense + full-text retrieval, filter-aware ANN, and exact, MVCC-visible re-scoring: a dedicated vector engine's feature set, as a PostgreSQL 17 extension.
Built by Evokoa · Fully-managed hosting at Polygres
pgContext is an Apache-2.0 PostgreSQL 17 extension that turns Postgres into a full AI search engine: dense vector search, metadata-filtered approximate search, and hybrid (dense + full-text) retrieval, all inside the database you already run.
Most retrieval stacks add a second service, copy your application data into it, and create a separate authorization, backup, and recovery boundary to keep in sync. pgContext keeps retrieval next to the data it searches: your ordinary PostgreSQL tables stay the source of truth for vectors, metadata, MVCC, ACL/RLS, backup, and replication. HNSW and other acceleration state are derived, rebuildable indexes (never a second copy that can drift), and every approximate result is re-scored exactly against the live row before it is returned, so a fast answer is still a correct, permission-safe answer.
At a glance: exact and persisted HNSW search · L2, inner-product, cosine, and L1 metrics · filters over registered columns and JSONB paths · MVCC/ACL/RLS and exact-score rechecks · collections, scroll, count, facets, and grouping · dense + full-text hybrid retrieval with reciprocal-rank fusion.
[!TIP] Looking for a managed version? We have launched a managed version of pgContext on polygres.com for full high performance AI Retrieval on Postgres.
Live demos
See pgContext’s retrieval in action (hosted on Polygres):
- Wikipedia hybrid search: query a Wikipedia-scale dataset with live semantic + keyword hybrid retrieval.
- Memory demo: an interactive hybrid-retrieval playground with adjustable fusion weights across retrieval channels.
Vector search
Standard GloVe-100-angular benchmark (1.18M vectors, cosine), both engines in one PostgreSQL 17 container with the same parallel build budget, scored against the dataset's own ground-truth neighbors. Full report →
pgContext serves persisted, page-native HNSW straight from durable PostgreSQL index pages. An HNSW plan never substitutes fixture candidates or silently exact-scans the whole collection. On the standard GloVe-100-angular benchmark (1,183,514 vectors, cosine), with pgContext and pgvector in the same PostgreSQL 17 container and built with the same parallel budget:
- Faster at the same recall. pgContext matches pgvector’s recall at every
search setting while answering each query 3.8-5.3× faster (for example,
0.910 recall@10 at 2.4 ms versus 13.0 ms at
ef_search512), and the advantage widens as you raise the recall target. - Higher recall for the same latency. Read the other way, that speed is quality: given roughly 2.5 ms per query, pgContext reaches 0.91 recall@10 where pgvector reaches 0.75, because it can afford far more search effort in the same time.
- Every answer is re-checked exactly. ANN candidates are resolved back to the live row and re-scored exactly, under PostgreSQL MVCC visibility, ACL/RLS, and SQL predicates: a fast answer is still a correct, permission-safe answer.
- Hybrid retrieval is built in. Dense vector search fused with PostgreSQL full-text ranking (reciprocal-rank fusion) ships in the extension, not as application glue.
All figures above are Apple M4 Pro (NEON). See the pgContext vs pgvector report for the full latency and recall curves, the three-system comparison that adds Qdrant (a strong, mature peer that leads at very high recall through per-query segment parallelism), and docs/benchmarks/pgvector.md for every lane.
Metadata filtering
Filtering is where vector search usually breaks: bolt a WHERE clause onto an
approximate search and recall quietly collapses as the filter gets selective.
pgContext treats filtering as part of the search, not an afterthought.
Write Qdrant-style filters over your registered PostgreSQL columns and JSONB
paths: must / should / must_not, equality, any / except, numeric and
datetime ranges, is_null / is_empty:
SELECT source_key, score
FROM pgcontext.search(
'docs', '[ ... ]'::vector,
'{
"must": [{"key": "tenant_id", "match": "acme"},
{"key": "price", "range": {"gte": 10, "lt": 20}}],
"should": [{"key": "metadata.topic", "match": {"value": "billing"}}],
"must_not": [{"key": "archived", "match": true}]
}'::jsonb,
10
);
What sets it apart:
- No filter index to build or maintain. Registering a column or JSONB path makes it filterable immediately; pgContext plans and runs the filtered search for you, no extra index required. Add an ordinary index (say, a btree on the column) later only when you want to speed a specific filter up; it’s an optimization, not a prerequisite.
- Filter-aware ANN, not post-filtering. Below a selectivity crossover pgContext scores exactly; above it, it pushes a single reusable mask through the persisted HNSW graph while excluded nodes still act as connectors, so recall holds up even when the filter is highly selective.
- One grammar for search, count, and facets. The same filter drives filtered search, counts, and facet aggregation: a cohesive retrieval API, not hand-assembled SQL per query.
- Safe and governed by PostgreSQL. Filters compile to a typed AST with bound parameters over registered fields only (no SQL injection, no mutating unregistered columns), and every result is re-checked against MVCC visibility and RLS/ACL before it is returned.
See Filters for the full grammar and field semantics.
Roadmap
pgContext 0.1.0 is the foundation, not the finish line. The goal is the most powerful AI search engine you can run inside PostgreSQL. On the way:
- More vector types and indexing. First-class
sparsevecandbitvec, quantized in-graph traversal with exact reranking, and non-dense ANN opclasses. - Lower latency and faster builds at scale. Segmented serving for per-query parallelism, background-worker compaction that keeps writes fast under sustained load, and parallel-build improvements that close the index-build-time gap.
- Drop-in pgvector compatibility. Run pgvector-spelled SQL unmodified, with in-place migration and no data movement.
- Graph-augmented retrieval. We plan to bring graph capabilities from our sister extension pgGraph into pgContext, so vector results can expand and re-rank along the relationships in your data (the pattern behind GraphRAG), without leaving Postgres or copying data between systems.
We’re upfront about what isn’t here yet: IVFFlat, x86 performance numbers, and full drop-in compatibility all live on the roadmap. See what’s not in 0.1.0 yet and the full roadmap.
Quickstart
Like pgvector, pgContext is one CREATE EXTENSION away once PostgreSQL can see
it:
CREATE EXTENSION pgcontext;
Pick whichever install path fits your setup: Docker (zero build) or
PGXN / source. The fastest is the pre-built Docker
image; it is multi-arch (linux/amd64 and linux/arm64) and works on macOS,
Linux, and Windows via Docker Desktop.
docker pull ghcr.io/evokoa/pgcontext:pg17-v0.1.0
docker run -d --rm \
--name pgcontext \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=pgcontext \
-p 5432:5432 \
ghcr.io/evokoa/pgcontext:pg17-v0.1.0
Verify the extension is loaded (uses psql inside the container, so you don’t need a local PostgreSQL client):
docker exec pgcontext psql -U postgres -d pgcontext \
-c "SELECT extname, extversion FROM pg_extension WHERE extname = 'pgcontext';"
If you have psql installed locally you can also connect directly:
psql -h localhost -U postgres -d pgcontext
(If the image tag is not yet available for your version, build and run the same demo locally with scripts/quickstart.sh.)
Build from Source
For a checkout or downloaded archive:
make install PG_CONFIG=/path/to/postgresql-17/bin/pg_config
psql -d postgres -c 'CREATE EXTENSION pgcontext;'
You need Rust 1.96.0, cargo-pgrx 0.19.1, PostgreSQL 17, its server development
headers, and a matching pg_config. See the complete
installation guide for Linux/macOS/Windows
shell support, verification, uninstall, cleanup, and troubleshooting.
Coming Soon: Package Registries
Package-manager installs are on the way and will be added here once available. Until then, use the Docker image or a source build above.
- PGXN:
pgxn install pgContext(distributionpgContext-0.1.0.zip). - Homebrew (macOS):
brew install pgcontextfrom the Evokoa tap.
Installing with an AI Agent
If you are an AI coding agent (or driving one) setting pgContext up in a fresh environment, follow AGENTS.md: it gives a deterministic, non-interactive install-and-verify recipe (Docker or source), the exact version pins, a copy-paste smoke test, and a short explanation of what the extension does so you can wire it into an application correctly.
Minimal Packaged Example
CREATE EXTENSION pgcontext;
CREATE TABLE docs (
id text PRIMARY KEY,
embedding vector(3) NOT NULL,
category text NOT NULL,
metadata jsonb NOT NULL
);
INSERT INTO docs VALUES
('postgres', '[1,0,0]', 'database', '{"language":"sql"}'),
('rust', '[0.8,0.2,0]', 'systems', '{"language":"rust"}'),
('vectors', '[0.7,0.1,0.2]', 'database', '{"language":"sql"}');
SELECT * FROM pgcontext.create_collection('docs', 'public.docs');
SELECT pgcontext.register_vector('docs', 'embedding', 'embedding', 3, 'cosine');
SELECT pgcontext.register_filter_column('docs', 'category', 'category');
SELECT pgcontext.upsert_points('docs', ARRAY['postgres', 'rust', 'vectors']);
SELECT source_key, score
FROM pgcontext.search(
'docs', '[1,0,0]'::vector,
'{"must":[{"key":"category","match":"database"}]}'::jsonb,
3
);
CREATE INDEX docs_embedding_hnsw
ON docs USING pgcontext_hnsw (
embedding pgcontext.vector_hnsw_cosine_ops
);
SELECT id, embedding OPERATOR(pgcontext.<=>) '[1,0,0]'::vector AS distance
FROM docs
ORDER BY embedding OPERATOR(pgcontext.<=>) '[1,0,0]'::vector
LIMIT 3;
The runnable, output-checked form is playground/demo.sql.
How It Works
pgContext registers application-owned tables and filterable fields in extension
catalogs. Exact search is the correctness oracle. The pgcontext_hnsw access
method stores metric-bound graph records on PostgreSQL index pages and returns a
bounded candidate set. Every candidate is resolved back to the live source row,
checked against PostgreSQL visibility and filters, and scored exactly before it
is returned. Acceleration state is rebuildable; application data never moves
out of PostgreSQL.
Feature Status
| Capability | V1 status |
|---|---|
| Dense vectors, exact metrics, casts, and aggregates | Stable |
| Registered-table exact search and metadata filtering | Stable |
| Collections, scroll, count, facets, and grouping | Stable |
| Dense plus PostgreSQL full-text hybrid retrieval | Stable |
| Dense L2, inner-product, cosine, and L1 HNSW | Implemented; performance-qualified on PostgreSQL 17 |
| Metadata-filtered ANN | Implemented with iterative and adaptive masked paths |
halfvec, sparsevec, and bitvec wrappers/opclasses |
Partial, experimental |
| PostgreSQL 17 | Supported V1 target |
| PostgreSQL 15, 16, and 18 | Post-V1 certification roadmap |
Comparison and Fit
| pgContext V1 | pgvector | Separate vector service | |
|---|---|---|---|
| Authoritative data | Ordinary PostgreSQL tables | PostgreSQL columns | Usually copied externally |
| Exact dense search | Yes | Yes | Usually |
| HNSW | Dense, page-native | Mature | Common |
| IVFFlat | Not implemented | Yes | Product-dependent |
| Metadata filtering | Registered PostgreSQL fields/JSONB | SQL predicates | Product-specific filters |
| Drop-in pgvector compatibility | No | Native | No |
For a detailed capability-by-capability view, including where pgvector or Qdrant is the better fit, see pgvector migration, the parity matrix, and the full three-way comparison.
Focused V1 Scope
V1 is optimized and release-gated for PostgreSQL 17, with exact retrieval, page-native dense HNSW, filtered ANN, and backend-local packed generations. Additional vector types are available for evaluation and controlled rollout. The roadmap grows that foundation with multi-major certification, quantized navigation, broader non-dense ANN, and more packaging options. See Known Issues and the roadmap for precise adoption guidance.
Documentation
PostgreSQL Authority, Community, and Security
PostgreSQL owns durability, transactions, visibility, roles, RLS, backups, and replication. Treat pgContext HNSW and other acceleration artifacts as rebuildable indexes, not an independent database.
Contributions and independent workload testing are welcome. Read CONTRIBUTING.md and the Code of Conduct. Use GitHub issues for public bugs and support questions. Do not disclose vulnerabilities publicly; follow SECURITY.md or email team@evokoa.com.
pgContext is built by Evokoa, the team behind pgGraph.