← SCRAM AI Lab

Tutoriales

pgvector para RAG en producción mexicana

pgvector vs Pinecone: $0 contra $70+ al mes para volúmenes hasta ~5M de embeddings. HNSW con m=16, ef_construction=64 da p50 de 15ms. Cuándo no usarlo.

May 21, 2026

6 lecturas

El costo escondido de no usar tu Postgres

Si ya corres Postgres en producción para datos transaccionales (usuarios, deals, transacciones), pagar $70-$300 al mes adicionales por Pinecone o Weaviate para vectores que se relacionan con esos mismos datos es ineficiente. pgvector lleva los embeddings a la misma DB y los une por SQL nativo a tus filas de negocio. En SCRAM corremos pgvector sobre el mismo Postgres del CRM en una GCP e2-standard-4 (4 vCPU, 16GB), sin servicio adicional, sin cuenta nueva, sin latencia de red entre dos sistemas. Costo marginal: $0/mes.

Cuándo NO uses pgvector

  • Más de ~10-20M de vectores: el índice HNSW empieza a comer RAM agresivamente. A esas escalas, un servicio especializado paga.
  • DB transaccional con carga pesada: si tu Postgres ya está al 70% de CPU sirviendo OLTP, agregarle queries vectoriales lo va a saturar. Mueve a una réplica o a una DB dedicada.
  • Requieres filtros geoespaciales avanzados sobre vectores con índices compuestos exóticos: Weaviate maneja esto mejor.
  • Necesitas multi-tenancy estricta con vector store por tenant: posible en pgvector pero engorroso.

Para todo lo demás (chatbots con RAG, semantic search en docs internos, recomendaciones por similitud, knowledge base, hasta unos cuantos millones de chunks), pgvector es la elección por default.

Setup mínimo en producción

-- Postgres 16+, pgvector 0.7+
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE doc_chunks (
  id BIGSERIAL PRIMARY KEY,
  doc_id UUID NOT NULL,
  org_id UUID NOT NULL,
  content TEXT NOT NULL,
  embedding vector(1536) NOT NULL,  -- text-embedding-3-small
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- HNSW para producción, NO ivfflat
CREATE INDEX doc_chunks_embedding_hnsw
  ON doc_chunks
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

CREATE INDEX ON doc_chunks (org_id);
CREATE INDEX ON doc_chunks (doc_id);

HNSW vs IVFFlat: usa HNSW

La doc oficial de pgvector lista los dos. En 2026, IVFFlat solo tiene sentido si tienes restricciones de memoria muy duras o si tu workload es exclusivamente offline. HNSW da mejor recall y latencia más estable a cambio de más RAM. Parámetros que funcionan en producción:

  • m = 16: conexiones por nodo. Más alto = mejor recall, más RAM.
  • ef_construction = 64: calidad del índice al construir. 64 es buen balance.
  • SET hnsw.ef_search = 40 por sesión: cuánto explorar al consultar. Súbelo a 80 si necesitas más recall, baja a 20 si quieres velocidad.

Con 100K chunks de 1536 dimensiones en e2-standard-4, latencia p50 de búsqueda es ~15ms. p99 sub-50ms. Suficiente para chatbot en vivo.

Query híbrida: el caso real

Pocas búsquedas son "similitud pura". Lo común es similitud + filtros de negocio (organización, tipo de doc, fecha, permisos). En pgvector se hace en un solo SELECT:

SELECT
  id,
  content,
  doc_id,
  1 - (embedding <=> $1) AS similarity
FROM doc_chunks
WHERE org_id = $2
  AND created_at > NOW() - INTERVAL '180 days'
  AND doc_id = ANY($3)  -- docs a los que el user tiene acceso
ORDER BY embedding <=> $1
LIMIT 8;

El operador <=> es distancia coseno. 1 - distancia da similitud entre 0 y 1. El planner de Postgres combina el índice HNSW con los filtros B-tree de manera competente; no necesitas hacer subqueries manuales.

Patrón de chunking que importa

  • Chunks demasiado grandes (>1500 tokens): el embedding se "promedia" semánticamente y pierdes precisión.
  • Chunks demasiado chicos (<100 tokens): pierdes contexto. Una frase aislada matchea cualquier cosa.
  • Sin overlap: la información que cruza el límite de chunk se pierde. Usa 10-15% de overlap.
  • No guardar el contexto del documento: el chunk debe traer título/sección como prefijo para que el LLM lo entienda al consumirlo.

Punto dulce: 500-800 tokens por chunk, 80 de overlap, prefijo con título del documento.

Lo que sigue rompiendo

  • VACUUM y REINDEX: HNSW se degrada con muchos updates. Programa REINDEX trimestral en horario bajo.
  • Costo de embeddings, no de pgvector: lo caro es generar embeddings, no almacenarlos. Cachea agresivamente y solo regenera si el contenido cambió.
  • Backups: los embeddings son grandes. Tu pg_dump va a crecer. Considera dump separado para tablas vectoriales.

Si tu RAG ya está en Pinecone, mídelo: ¿qué pasaría si migraras a pgvector mañana? La respuesta para la mayoría de proyectos sub-5M de vectores es "ahorras varios miles al año y simplificas el stack". ¿Cuál es tu volumen real de embeddings?

pgvector
rag
postgres
ai-native-saas
← Volver a SCRAM AI Lab