Skip to content

Indexes ​

Index creation is manual by default. A missing ANN index is the usual reason search() is slow.

sql
SELECT postvec.create_vector_index('public.docs', 'body');

Expected

status().has_vector_index becomes true. If a usable index already exists (including one you built), the function leaves it as-is and leaves ownership with you.

Only indexes created by postvec carry the extension-dependency stamp and are dropped at teardown. A name you chose yourself stays yours.

Modes (index_mode on enable / adopt) ​

ModeWhen the index appearsLock
manual (default)On an explicit create_vector_index() or CREATE INDEX CONCURRENTLYSelected by you
immediateIn the enable() / adopt() transactionBlocking CREATE INDEX
autoAfter the worker sees the queue drainBlocking, and occupies the only worker

In the extension both non-manual modes are blocking. PostgreSQL forbids CONCURRENTLY inside those transactions. auto also pauses embedding, migrations, cursor backfill and heartbeats for that database while it builds. For that reason auto is opt-in and is meant for small, quiet tables. Large or write-heavy tables should stay on manual and use:

sql
CREATE INDEX CONCURRENTLY docs_body_hnsw
  ON public.docs
  USING hnsw (body_semantic vector_cosine_ops);

On managed PostgreSQL the sync worker in postvec-server builds an auto index after the queue drains, on its own connection, with CREATE INDEX CONCURRENTLY (index_concurrently, on by default), so table writes continue during the build.

Match the opclass to the entry's distance (vector_cosine_ops, vector_l2_ops, vector_ip_ops). In the extension, above 2000 dimensions both non-manual modes refuse and suggest a halfvec expression index. Managed builds a halfvec expression above 2000 dimensions.

immediate is refused for chunked entries. Index the destination after backfill.

Auto-build eligibility ​

In the extension the automatic build needs all of: registry state active, index_error IS NULL, no live migration (including awaiting_index), no cursor backfill, no pending or claimed job, dim <= 2000 and no usable index yet.

A failed automatic build records status().index_error and stops retrying. An explicit create_vector_index() call clears the error after readiness is satisfied.

doctor ranks index findings: failed automatic build -> wrong opclass -> manual with no index -> auto still waiting (informational). A suitable user-created index passes.

Constraints ​

auto performs a blocking index build

In the extension the worker runs CREATE INDEX and stops embedding for the duration.

Index ownership follows who created the index

User-created indexes remain user-owned. Dropping a postvec-created index from an auto entry causes the worker to rebuild it.