Every pgvector tutorial ends at the first similarity query. Production starts there: index build memory, replica behavior, backup growth, vacuum patterns and what the planner does when vector search meets a WHERE clause. This playbook enables the extension the way a DBA does — with the ops questions answered before the feature ships.
Tier: Core · Workflow area: Vector & AI Features · ~40 minutes
Vector search inside Postgres is the DBA's cleanest claim on the AI estate: no new platform, no data movement, your existing backup, HA and access-control machinery. But the demo hides real operational surface. This playbook walks the enablement in operator order — capacity first, index second, query behavior third — so the feature lands with the same rigor as any other schema change.
Do the capacity math before CREATE EXTENSION. A vector column of dimension d costs roughly 4d + 8 bytes per row; the HNSW index adds the same order again. Have AI build the forecast:
Act as a PostgreSQL capacity planner. Table: 4.2M rows, adding
vector(1024). Estimate: table growth, HNSW index size (m=16),
maintenance_work_mem for a sane build, WAL volume during a full
embedding backfill, and pg_dump size impact. Show formulas,
then numbers. Flag what changes at 10x rows.
Sanity-check its arithmetic: 4.2M × 1024 dims ≈ 17 GB of raw vector data before index overhead. If the model's numbers disagree with the formula, the formula wins.
Enable the extension and add the column as a gated change. This is DDL on production — it goes through the pb-10 migration gate like anything else:
CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE products ADD COLUMN embedding vector(1024);
Confirm the version — HNSW needs pgvector 0.5+, and 0.7+ brings halfvec and sparse types worth knowing about:
SELECT extversion FROM pg_extension WHERE extname = 'vector';
Build the HNSW index with memory set deliberately, off-peak. The build wants the graph in memory; starving it makes builds crawl:
SET maintenance_work_mem = '4GB';
SET max_parallel_maintenance_workers = 4;
CREATE INDEX CONCURRENTLY idx_products_embedding
ON products USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
CONCURRENTLY avoids blocking writes but roughly doubles build time — the right trade on a live table. Time the build and record peak memory; that number is your maintenance-window budget for every future rebuild.
Interrogate the plan where vector search meets filters. The classic production surprise: ANN index scans return the ef_search nearest neighbors before your WHERE clause filters them — a selective filter can leave you with 3 results when the app asked for 20:
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, name FROM products
WHERE category = 'outdoor' AND in_stock
ORDER BY embedding <=> $1 LIMIT 20;
If filtered result counts come up short, raise hnsw.ef_search (session-level), or use pgvector 0.8+ iterative index scans which keep fetching candidates until the LIMIT is satisfied. Verify which behavior your version has — do not trust the model's memory of it.
Answer the replica and backup questions in writing. Ask AI to draft the ops annex, then verify each claim against your setup: HNSW indexes replicate physically and are usable on hot standbys; logical replication rebuilds them on the subscriber; base backups and pg_dump both grow by the table-plus-index figure from step 1. Run one full backup-and-restore timing test with vectors in place before go-live — measured, not estimated.
Set the vacuum and monitoring baseline. Dead tuples from re-embedding updates bloat both heap and index. Watch pg_stat_user_tables for the vector table, alert on index size growth beyond forecast, and schedule REINDEX CONCURRENTLY guidance for when deletes accumulate — HNSW does not shrink on its own.
VECTOR type plus DiskANN indexing plays the same role; memory and maintenance questions map to index build resource governance. See pb-32 for the full translation.maintenance_work_mem ceilings or extension versions; check the version your provider pins before promising HNSW-era features, and watch IOPS billing during builds and backfills.Embedding backfills move your data through whatever model endpoint generates the vectors. If rows contain customer text, that is a data transfer — route it through a tenant-approved or local model (see pb-29) and record it in your processing register before the backfill runs.
The demo proves pgvector works; the capacity math, build timing, plan reads and backup tests prove you can run it. Do the four before go-live and vector search becomes just another feature your database serves — which is exactly the point.