AI agents
Vector-DB voor octrooizoek: Pinecone, Weaviate, pgvector
Zondag 22:14 in Eindhoven. De re-embedding van 1,4M octrooiclaims hangt op 38%, de auteur van de runbook zit in Vietnam, en maandagochtend start de prior-art queue over negen uur.

Zondag, 22:14, Eindhoven. De on-call engineer van een octrooibureau met 21 medewerkers krijgt een Slack-melding van de embedding-pipeline: de wekelijkse re-embedding van 1,4M octrooiclaims is op 38% blijven hangen. De auteur van de runbook zit op vakantie in Vietnam. De eerste prior-art queue van maandagochtend start over negen uur.
Dit is het moment dat bepaalt welke vector-database je echt hebt gekozen. Niet de demo van dinsdag. Het ticket van 22:14.
Afgelopen voorjaar hebben we acht weken meegelopen om dat bureau te helpen kiezen welke embedding-laag ze gingen draaien. Drie kandidaten haalden de eindronde: Pinecone serverless, Weaviate op Hetzner, en een zelfgebouwde pgvector-opstelling op een Postgres 16-cluster dat het bureau al draaide. Het scorebord had drie kolommen: kosten per octrooi op volle belasting, een vector-historie die je later kunt afspelen voor de 20-jaars bewaarplicht uit de Rijksoctrooiwet, en wie de index daadwerkelijk patcht om 22:14 op zondag.
De workload, in echte cijfers
Het bureau doet prior-art onderzoek over EPO, USPTO en WIPO via de agent die we bovenop hun corpus hebben gebouwd. Eenentwintig octrooigemachtigden en paralegals; vijf tot vijftien zoekacties per persoon per werkdag; ruwweg 2.800 retrievals per week. Elke retrieval haalt een top-k van 200 uit de vector-index, geeft de chunks aan een reranker, en daarna aan een citatie-stap die de claim-nummers terugresolved naar de bron-PDF's.
Het corpus telt 1,4M claim-embeddings en groeit met ongeveer 14.000 per week zodra nieuwe aanvragen worden gepubliceerd. Embeddings zijn 1.536-dimensionaal. Het team beoordeelt het embedding-model elk kwartaal opnieuw; als ze wisselen, wordt het hele corpus over een weekend opnieuw geëmbed. Dat is de job die vastliep.
Drie getallen dragen de hele beslissing: opslagkosten per miljoen vectoren, querykosten per duizend retrievals, en de prijs van één ongeplande engineer-uur om 22:14.
Pinecone serverless: snel live, traag te auditen
De serverless-tier van Pinecone is de snelste route naar een werkende index. We hadden in één middag een 1,4M-vector-index draaien met p95 onder de 90ms. Bij deze belasting kwam de rekening uit op zo'n €480 per maand all-in. Goedkoop, op elke maatstaf die de volgende twee kolommen negeert.
Bij de audit-kolom werd Pinecone lastiger. De Rijksoctrooiwet wil dat een bureau het dossier 20 jaar na sluiting bewaart. Voor een prior-art search betekent dat: in 2046 moet je kunnen aantonen welke embedding van welke claim-tekst welke hit teruggaf op welke datum. De index van Pinecone is muteerbaar. Je kunt een serverless-index snapshotten, maar snapshots zijn geen volwaardige versie-laag. Wil je een retrieval uit 2026 in 2034 opnieuw afspelen met exact de 2026-staat van de index, dan moet je collection-backups, metadata-blobs en een bevroren kopie van de embedding-model binary aan elkaar knopen. Kan. Niet eenvoudig te auditen.
De 22:14-kolom is de echte. Als de re-embedding job vastloopt, kan de on-call engineer niet in Pinecone SSH'en. Die opent een supportticket. De reactietijd op zondag om 22:14 in Europa meet je in uren, niet in minuten.
Weaviate op Hetzner: flexibel, tweede product
Weaviate is op vrijwel elke dimensie de middenoptie. Twee AX102-nodes bij Hetzner (Ryzen 9 7950X3D, 128GB RAM, NVMe) draaiden voor in totaal zo'n €220 per maand. Met HNSW en een warme cache zat p95 rond de 60ms. Het schema-model laat je meerdere embedding-versies naast elkaar dragen, wat echt handig is voor de modelwissel per kwartaal.
De kosten per retrieval waren bij volle belasting de beste van de drie. Het audit-verhaal was werkbaar: backup-restore is in Weaviate een first-class operatie, en je kunt per vector metadata meedragen voor embedding-model-versie en retrieval-timestamps.
Het probleem met Weaviate, voor dit bureau, was de operationele voetafdruk. Ze draaiden al een Postgres-cluster voor dossiers, facturatie en de Nederlandstalige documentopslag. Weaviate erbij betekende dat de on-call engineer een tweede stateful systeem moest leren, met zijn eigen backup-verhaal, upgrade-cadans en failure modes. Het bureau heeft anderhalve engineer. Om 22:14 moet die engineer een bekend log greppen, geen documentatie scannen.
pgvector op Postgres 16: saai, in eigen beheer, herhaalbaar
De derde optie was de minst spannende, en die hebben we uitgerold.
pgvector 0.7 op Postgres 16 geeft je HNSW-indexes binnen de database die het bureau toch al draait. De tabel ziet er zo uit:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE claim_embedding (
claim_id bigint NOT NULL,
source text NOT NULL, -- 'EPO' | 'USPTO' | 'WIPO'
embedded_at timestamptz NOT NULL DEFAULT now(),
model_version text NOT NULL, -- e.g. 'mxbai-embed-large-v1'
embedding vector(1536) NOT NULL,
PRIMARY KEY (claim_id, model_version)
);
CREATE INDEX claim_embedding_hnsw
ON claim_embedding USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
Het retrieval-pad is één SQL-query die de bestaande applicatiestack van het bureau al kan loggen, tracen en terugrollen:
SELECT claim_id, source, model_version,
1 - (embedding <=> $1) AS score
FROM claim_embedding
WHERE model_version = $2
ORDER BY embedding <=> $1
LIMIT 200;
p95 op de index met 1,4M rijen, met ef_search opgeschroefd naar 80, kwam uit op 110ms op de bestaande 8-core productienode van het bureau. In absolute zin trager dan Pinecone, snel genoeg dat de reranker de bottleneck is.
Het interessante zit hem in de kolommen die het bureau níet hoefde toe te voegen. embedded_at en model_version staan al in de rij. Point-in-time recovery op Postgres 16 dekt de vector-kolom net zo goed als elke andere tabel, wat betekent dat het bewaarplicht-verhaal voor de embedding-laag hetzelfde verhaal is dat het bureau al voor dossiers had geschreven: WAL archiveren naar onveranderlijke object-storage, retentie 20 jaar, restore-oefening eens per kwartaal.
Als je een managed vector-DB draait voor een Nederlands octrooibureau en je '20-jaars audit'-plan luidt 'we exporteren eens per kwartaal JSON-snapshots naar S3', lees de Rijksoctrooiwet dan nog eens. Je hebt een verdedigbare keten nodig van claim-tekst naar embedding naar retrieval, niet een mapje met bestanden.
De 20-jaars replay-test
De bewaarplicht uit de Rijksoctrooiwet geldt voor octrooidossiers twintig jaar vanaf sluiting. Voor een prior-art search agent betekent dat: een derde partij kan in 2044 vragen waarom jouw octrooigemachtigde US-1234567 als prior art citeerde voor een aanvraag uit 2026 — en dan moet je de retrieval kunnen tonen.
We hebben de replay-test als doorslaggevende keuzevraag genomen. Voor elke kandidaat: reconstrueer het exacte top-50-resultaat van een query uit 2026, met alleen artefacten waar je in 2044 nog bij kunt.
Voor pgvector was het antwoord een one-liner. De query, de model-versie en de rij-staat op moment van retrieval staan allemaal in Postgres; WAL plus een snapshot van de embedding-model binary in onveranderlijke storage speelt de search opnieuw af. Voor Weaviate was het antwoord drie pagina's runbook. Voor Pinecone was het antwoord afhankelijk van een leverancier die in 2044 misschien wel of niet dezelfde SKU verkoopt.
Kosten per octrooi bij 2.800 runs per week
Genormaliseerd op de workload van het bureau — 2.800 retrievals per week, 1,4M vectoren, kwartaal-re-embeds — zagen de all-in kosten per retrieval er ongeveer zo uit:
- Pinecone serverless: ~€0,04 per retrieval, plus een operationeel risico dat je niet kunt inboeken in de 22:14-kolom.
- Weaviate op Hetzner: ~€0,02 per retrieval, plus een kwart-FTE platform engineering die het bureau niet had.
- pgvector op Postgres 16: ~€0,004 marginaal per retrieval, omdat de database al betaald was. Re-embedding compute is de enige noemenswaardige nieuwe regel.
Kosten per retrieval is het paradenummer waarmee elke leverancier zijn pitch opent. Het is ook de kleinste van de drie kolommen. Kies de laag die de zondagavond overleeft.
Wat we hebben uitgerold
We hebben pgvector uitgerold op de bestaande Postgres 16-primary van het bureau, met een streaming-replica voor leesverkeer, claim_embedding gepartitioneerd op source, en de re-embedding job zo geschreven dat hij elke 50.000 rijen een checkpoint wegschrijft naar een reembed_progress-tabel. De vastloper op zondag 22:14 is nu één SELECT * FROM reembed_progress ORDER BY started_at DESC LIMIT 1 verwijderd van 'hervat vanaf rij 532.001'. De on-call engineer hoeft op het slechtste moment van de week nooit meer een nieuw systeem te leren.
Toen we de prior-art AI-agent voor dat Eindhovense bureau bouwden, kwamen we steeds terug op één punt: de vector-database is de laag waar zowel de modelwissel als de bewaarplicht doorheen lopen. We hebben dat opgelost door de embedding gewoon als nóg een kolom te behandelen in een tabel die het team al in beheer had, en het audit-verhaal één keer te schrijven in plaats van twee keer.
Audit van vijf minuten voor je eigen setup: open de tabel waarin je embeddings staan, en kijk of er een embedded_at- en een model_version-kolom in zit. Zo niet, dan heb je nog geen replay-verhaal.
Kern
Voor een 20-jaars audit trail onder de Rijksoctrooiwet wint de vector-database die je team al draait het van degene die 50ms sneller is.
FAQ
Schaalt pgvector echt voorbij een paar miljoen vectoren?
Ja. HNSW in pgvector 0.7+ kan tientallen miljoenen vectoren aan op één goed afgestelde node. Het bureau zit in de enkele miljoenen, ruim binnen de comfortzone.
Waarom hebben jullie Qdrant of Milvus niet meegetest?
Allebei goede producten. De doorslaggevende kolom was operationele bekendheid voor een team van anderhalve engineer, en het bureau draaide al Postgres. Een tweede stateful systeem was de prijs die we weigerden te betalen.
Wat gebeurt er met oude embedding-versies als je van model wisselt?
Die houden we. De primary key (claim_id, model_version) zorgt dat elke historische retrieval kan worden afgespeeld tegen exact de embedding die hij teruggaf. Dat is de 20-jaars audit trail.
Is Pinecone voor elke gereguleerde workload de verkeerde keuze?
Nee. Het is de verkeerde keuze als de toezichthouder een replay trail wil die je kunt verdedigen zonder medewerking van de leverancier. Voor kortere retentie of niet-geauditeerde workloads is de snelheid waarmee je live gaat echt nuttig.
Hoe herstart je een vastgelopen re-embedding job zonder de afgemaakte rijen opnieuw te doen?
Checkpoint de voortgang elke N rijen naar een kleine tabel, sleutel de job op (model_version, batch_id), en laat de worker rijen overslaan waar dat paar al bestaat. Hervatten wordt een SELECT, geen migratie.