PostgreSQL pgvector in Production: HNSW Indexes, Hybrid Semantic Search & RAG Without Dedicated Vector DBs

Hamza Fazal, Founder, DEESUHamza FazalFounder, DEESU6 min readWeb Development

When engineering teams began building generative AI applications and Retrieval-Augmented Generation (RAG) pipelines in 2023 and 2024, the default advice was to spin up a specialized, proprietary vector database: Pinecone, Qdrant, Weaviate, or Milvus. Founders and enterprise architects quickly added these services to their infrastructure stacks.

By 2026, the reality of running a specialized vector database alongside a relational database has become clear: it introduces a painful Dual-Database Sync Tax. Whenever a user updates their profile, deletes a document, or revokes a workspace permission in PostgreSQL, an asynchronous background worker has to sync that mutation to the external vector database. When that worker lags or fails, the AI chatbot hallucinates stale documents or, worse, leaks deleted private data across tenant boundaries.

Enter pgvector. With the release of version 0.7+ and native HNSW (Hierarchical Navigable Small World) indexing support, PostgreSQL can effortlessly query millions of 1536-dimensional embeddings with sub-5 millisecond response times—all while preserving ACID guarantees, relational joins, and Row-Level Security (RLS).

In this practical engineering guide, we walk through configuring pgvector in production, compare HNSW vs. IVFFlat indexing, analyze vector quantization strategies to slash RAM costs, and write production SQL for Hybrid Search using Reciprocal Rank Fusion (RRF).

PostgreSQL Hybrid Search and RAG Architecture with pgvector and HNSW Diagram 2026
PostgreSQL Hybrid Search Architecture: User query generates text embedding -> Concurrent dual execution of pgvector HNSW cosine distance search and tsvector full-text search -> Combined via Reciprocal Rank Fusion (RRF) SQL query into the LLM context window.

1. The True Cost of Dedicated Vector Databases vs. PostgreSQL

To understand why modern engineering teams are ditching standalone vector SaaS platforms, compare the operational trade-offs:

Architectural FactorDedicated Vector DB (Pinecone / Weaviate)PostgreSQL with pgvector (Modern 2026)
Infrastructure OverheadSeparate managed SaaS cluster or dedicated pod cluster.Zero: lives inside your existing PostgreSQL instance.
Data Consistency & SyncRequires Kafka / Debezium CDC pipelines; vulnerable to drift.100% ACID transactional consistency in a single write transaction.
Tenant Authorization & SecurityMust duplicate access control lists (ACLs) across both DBs.Native PostgreSQL Row-Level Security (RLS) filters vectors automatically.
Relational JoinsImpossible (must query vector DB, then query SQL DB).Native SQL JOINs combining metadata, user permissions, and embeddings.
Base Monthly Hosting Cost$70 to $400+/month for managed dedicated clusters.$0.00 additional cost (runs on your existing RDS / Supabase instance).

2. Enabling pgvector and Schema Architecture

Setting up pgvector requires enabling the extension and creating a table with a strongly-typed vector column. For OpenAI text-embedding-3-small or standard open-source embeddings, dimensions are typically 1536:

-- Enable the pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

-- Production Documents & Embeddings Table
CREATE TABLE documents (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL,
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  content_tokens INTEGER NOT NULL,
  -- Full-text search vector column
  tsv_content TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', title || ' ' || content)) STORED,
  -- 1536-dimensional vector embedding column
  embedding VECTOR(1536),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Full-text GIN index for keyword searches
CREATE INDEX idx_documents_tsv ON documents USING GIN(tsv_content);

3. Indexing Performance: Why HNSW Beats IVFFlat

pgvector supports two primary index types: IVFFlat (Inverted File Flat) and HNSW (Hierarchical Navigable Small World). Understanding the difference is vital for production scalability:

  • IVFFlat: Partitions vectors into clusters using k-means. While IVFFlat builds faster and consumes less RAM, it suffers from a fatal flaw in dynamic applications: you must build the index *after* loading data. As your application writes new records, search recall degrades rapidly unless you drop and re-index the entire table.
  • HNSW: Constructs a multi-layer geometric graph of vector connections. HNSW supports real-time concurrent inserts without degrading search recall, achieves 99%+ recall accuracy, and delivers sub-5ms query latencies under high read concurrency.

Here is how to create an optimized HNSW index in PostgreSQL using cosine distance:

-- Create HNSW index using Cosine Distance operator (<=>)
-- m = 16 (number of bidirectional links per node, default 16)
-- ef_construction = 64 (size of dynamic candidate list, default 64)
CREATE INDEX idx_documents_embedding_hnsw 
ON documents 
USING hnsw (embedding vector_cosine_ops) 
WITH (m = 16, ef_construction = 64);

Pure vector semantic search excels at fuzzy conceptual matching. For example, if a user searches for *'How do I cancel my plan?'*, vector search matches documents discussing *'Subscription termination and refund guidelines'*, even though the words are completely different.

However, vector search fails miserably on exact keywords: product part numbers, error codes (ERR_CONNECTION_REFUSED), specific employee names, or API slugs (/v1/auth/token). Embedding models project alphanumeric tokens into generic sub-word clusters.

The solution is Hybrid Search: running a vector cosine search and a PostgreSQL full-text tsvector search simultaneously, and fusing their rankings using Reciprocal Rank Fusion (RRF) directly in a single SQL query:

-- Production Hybrid Search using Reciprocal Rank Fusion (RRF)
WITH semantic_search AS (
  SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> $1::vector) as rank
  FROM documents
  WHERE tenant_id = $2
  ORDER BY embedding <=> $1::vector
  LIMIT 20
),
keyword_search AS (
  SELECT id, ROW_NUMBER() OVER (ORDER BY ts_rank_cd(tsv_content, websearch_to_tsquery('english', $3)) DESC) as rank
  FROM documents
  WHERE tenant_id = $2 AND tsv_content @@ websearch_to_tsquery('english', $3)
  LIMIT 20
)
SELECT 
  d.id, 
  d.title, 
  d.content,
  -- RRF scoring formula: 1 / (60 + rank)
  COALESCE(1.0 / (60 + s.rank), 0.0) + COALESCE(1.0 / (60 + k.rank), 0.0) AS hybrid_score
FROM documents d
LEFT JOIN semantic_search s ON d.id = s.id
LEFT JOIN keyword_search k ON d.id = k.id
WHERE s.id IS NOT NULL OR k.id IS NOT NULL
ORDER BY hybrid_score DESC
LIMIT 10;

5. Slashing RAM Usage with Halfvec & Quantization

High-dimensional vector embeddings are memory-intensive. One million 1536-dimensional vectors stored as standard 32-bit floating points (float4) consume roughly 6.14 Gigabytes of raw RAM, excluding HNSW graph indices.

To optimize memory consumption on standard cloud database tiers, pgvector supports halfvec (16-bit half-precision floats). Storing vectors as halfvec(1536) cuts raw memory requirements by 50% (down to 3.07 GB) while preserving 99.8% of mathematical cosine distance precision. For massive million-row document collections, this allows engineering teams to stay on affordable 8GB or 16GB RAM database instances.

6. Production pgvector Deployment Checklist

Before launching your semantic search or RAG pipeline to production, verify these five architectural prerequisites:

  • Use HNSW indexes instead of IVFFlat to support continuous real-time database writes without index degradation.
  • Enforce PostgreSQL Row-Level Security (RLS) on document tables to prevent multi-tenant embedding leaks.
  • Combine vector cosine distance with tsvector full-text search using Reciprocal Rank Fusion (RRF) for 100% keyword precision.
  • Set hnsw.ef_search = 100 in session parameters to balance query latency vs recall accuracy.
  • Consider halfvec 16-bit float quantization to cut database RAM consumption in half.

Frequently asked questions

Yes. Benchmarks on PostgreSQL 16 and 17 demonstrate that with HNSW indexing, pgvector effortlessly manages 10M+ 1536-dimensional vectors with sub-10ms query latencies on standard cloud hardware (e.g. AWS RDS or Supabase Pro).

Cosine distance (<=>) measures the angular difference between vectors regardless of magnitude, ideal for normalized text embeddings. L2 Euclidean distance (<->) measures spatial distance. Inner product (<#>) is fastest for vectors that are strictly pre-normalized to unit length.

Embedding models convert text into high-dimensional semantic concepts rather than preserving character strings. Rare alphanumeric strings, serial numbers, error codes, and specific names get blurred across neighboring token embeddings. Hybrid search combining BM25 keyword search solves this problem completely.

Because embeddings live in standard relational tables, PostgreSQL automatically applies RLS policies at the query engine level. Even if an AI agent prompts an unscoped vector similarity search, PostgreSQL mathematically filters out records belonging to other tenants before returning vector results.

Reciprocal Rank Fusion is an algorithmic ranking function that combines ranked search results from multiple distinct retrieval algorithms (such as keyword search and vector semantic search) using the formula 1 / (60 + rank). It normalizes disparate score scales without requiring complex machine-learning calibration.

Sources

ShareLinkedInX
Hamza Fazal, Founder, DEESU

Written by

Hamza Fazal

Founder, DEESU

Muhammad Hamza Fazal is the Founder of DEESU. An Android and full-stack web developer and digital marketer based in Islamabad, he founded DEESU in May 2022 and leads its engineering operations, product strategy, and client software delivery.

More from Hamza

Need help with this?

Reply within 1 business day

Tell us what you're building.

Send the problem, not a polished brief. We'll tell you what it actually takes to ship it: stack, timeline and cost, before you commit to anything.