pgvector

pgvector: PostgreSQL as a Vector Database

By Carlos Montiel | Enterprise AI Solutions Architect | guatemalia.com
Leer en español →
✍️ Carlos Montiel 📂 pgvector ⌛ 11 min read
A complete guide to pgvector: installation, configuration, storing embeddings, and semantic search directly in PostgreSQL.

What is pgvector?

pgvector is an open-source PostgreSQL extension for high-dimensional vectors and similarity search. It lets you use PostgreSQL as a vector database without adding separate systems like Pinecone or Weaviate.

Why does it matter? Most companies already run PostgreSQL in production. With pgvector, they implement RAG and semantic search without adding operational complexity or extra infrastructure costs.

Capabilities:

Installing on Docker and Ubuntu

Docker (fastest):
docker run -e POSTGRES_PASSWORD=password -p 5432:5432 ankane/pgvector

Ubuntu/Debian:
sudo apt install postgresql-15-pgvector
psql -c "CREATE EXTENSION IF NOT EXISTS vector;"

Vector distance operators

pgvector uses special operators for search:

Cosine distance is the most appropriate for text embeddings because it measures the vector's direction, not its magnitude.

HNSW index: fast search at scale

For large collections (>100K vectors), the HNSW index enables approximate searches in milliseconds:

Key parameters:

For production with 1M+ vectors: m=16, ef_construction=128 is a good starting point.

Code example

-- pgvector: create table and search for similar embeddings
CREATE EXTENSION IF NOT EXISTS vector;

-- Documents table with embeddings
CREATE TABLE documents (
    id         BIGSERIAL PRIMARY KEY,
    title      TEXT NOT NULL,
    content    TEXT,
    category   VARCHAR(50),
    embedding  vector(1536),
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- HNSW index for fast search
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 128);

-- Semantic search: top-5 most similar filtered by category
SELECT title, category,
       1 - (embedding <=> '[0.031, -0.401, ...]'::vector) AS similarity
FROM documents
WHERE category = 'HR'
ORDER BY embedding <=> '[0.031, -0.401, ...]'::vector
LIMIT 5;

-- Python: insert an embedding generated with OpenAI
import psycopg2
from openai import OpenAI

def index_document(title, content, category, conn):
    client = OpenAI()
    embedding = client.embeddings.create(
        model="text-embedding-3-small",
        input=content
    ).data[0].embedding

    with conn.cursor() as cur:
        cur.execute(
            "INSERT INTO documents (title, content, category, embedding) VALUES (%s,%s,%s,%s)",
            (title, content, category, embedding)
        )
    conn.commit()

Need to implement this at your company?

Carlos Montiel is an enterprise AI solutions architect with experience in LLMs, Agents, RAG, and orchestration in Guatemala and Latin America.

Contact Carlos Montiel
Carlos Montiel
Enterprise AI Solutions Architect · guatemalia.com

Specialist in LLMs, AI Agents, RAG, LangChain, and LangGraph for companies in Guatemala and Latin America. For implementation inquiries: guatemalia.com/en/#contact