M MemberIntel KB
Activity Decisions

decision

ADR-0003: pgvector for V1, tenant_id as partition key

ADR-0003 (Accepted (resolves SPEC Open Q9), 2026-05-08): pgvector for V1, tenant_id as partition key.

Status: Accepted (resolves SPEC Open Q9)
Date: 2026-05-08
Deciders: Seth (Lead Architect), Blair (CEO sign-off pending)

Context

SPEC Open Q9: vector store choice. Per arch-overview.md the architecture
deep-dive recommends pgvector for V1. Per the cost review and SPEC §10,
per-tenant data isolation is a security invariant.

Decision

pgvector for V1. Every vector row carries a tenant_id column. RLS
policy enforces current_setting('app.tenant_id')::uuid = tenant_id on
every row read. Application code must call SET LOCAL app.tenant_id = '<uuid>' at the top of every request handler before any vector query.
Cross-pollination job runs as a separate Postgres role with explicit
RLS bypass — that role’s lifecycle is a future ADR (deferred to Phase 2).

Pinecone migration path: connection-string swap + per-tenant namespace
mapping, no schema change. The tenant_id column maps to a Pinecone
namespace 1

.

Consequences

Positive:

  • Resolves SPEC Open Q9.
  • Single Postgres instance for V1; no separate vector DB ops cost.
  • RLS provides defense in depth even if app code forgets to filter.

Negative / costs:

  • pgvector at large scale (>10M vectors) may need tuning or eventual Pinecone migration.

Mitigations:

  • Schema designed so migration is a connection-string swap.

Alternatives considered

  • Pinecone from day one — rejected: extra ops surface for V1 scale (<1M vectors expected).
  • Qdrant or Weaviate self-hosted — rejected: introduces a second DB to operate.
  • In-Postgres without pgvector (TF-IDF or embedding-as-array) — rejected: forfeits the only real reason to be in pgvector.
For: S Seth Shoultes A AI Engineer B Blair Williams S Santiago Perez Asis P Product Lead