Quick start local
A container with PostgreSQL, postvec and one local model (MiniLM). Inference runs inside that container.
The same SQL against postvec-server is quick start remote.
1. Run the local image
docker run -d --name postvec \
-e POSTGRES_PASSWORD=demo \
-e POSTGRES_USER=app \
-e POSTGRES_DB=app \
-p 127.0.0.1:5433:5432 \
ghcr.io/univec-ai/postvec:0.5.0-2-pg18-localWait until status is healthy (PostgreSQL is up and MiniLM is loaded):
docker inspect --format '{{.State.Health.Status}}' postvecThe image creates the extension in POSTGRES_DB on first initialization only.
Optional
postvec-healthcheck exits 0 when the worker and engine are ready. postvec.embed() returning 384-d also proves inference:
docker exec postvec postvec-healthcheck
docker exec -i postvec psql -U app -d app -c \
"SELECT vector_dims(postvec.embed(
'the isolated image performs inference',
'sentence-transformers-all-minilm-l6-v2'
)::vector);"2. Enable a column and insert
docker exec -i postvec psql -U app -d app <<'SQL'
CREATE TABLE docs (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
body text,
category text
);
SELECT postvec.enable(
'public.docs', 'body',
model => 'sentence-transformers-all-minilm-l6-v2',
create_fts_index => true
);
INSERT INTO docs (body, category) VALUES
('quarterly revenue guidance was raised after strong subscription growth',
'finance'),
('migrating embedding models normally requires re-embedding source text',
'engineering'),
('the office plants need watering twice a week',
'office');
SELECT relation, pending_jobs, dead_jobs
FROM postvec.status();
SQLVectors fill asynchronously. After INSERT commits, wait until pending_jobs = 0 and every body_semantic is non-NULL:
docker exec -it postvec psql -U app -d appthen (in psql):
SELECT count(*) FILTER (WHERE body_semantic IS NOT NULL) AS filled,
count(*) AS total
FROM docs;Expected
filled = total, pending_jobs = 0, dead_jobs = 0. On this image that is usually a second or two.
3. Index and search
Index (one-time):
SELECT postvec.create_vector_index('public.docs', 'body');Search:
SELECT d.id, d.body,
round(s.rrf_score::numeric, 5) AS score,
s.semantic_rank, s.fts_rank
FROM postvec.search(
'public.docs', 'body',
'switching AI models without redoing the work'
) AS s
JOIN public.docs AS d ON d.id = s.pk_value::bigint
ORDER BY s.rrf_score DESC;Expected
The engineering row ranks highly despite almost no keyword overlap. status().has_vector_index is true.
4. Remove the container
docker rm -f postvecAn existing cluster uses packages then configure. RDS, Aurora, Cloud SQL, Azure, Supabase and Neon use managed PostgreSQL.