ADR-0004 — PostgreSQL as the metadata source of truth

Context

A file is two writes — bytes (object store) and metadata (a row). They cannot be written atomically across two systems, so one must be authoritative. Getting this wrong yields orphaned blobs or dangling references (R2) — silent corruption, the worst class of bug for a storage product. We also need transactions, relational integrity (the namespace tree, versions, shares), Row-Level Security for tenant isolation (ADR-0007), and a transactional outbox (ADR-0006).

Decision

PostgreSQL is the single source of truth for all metadata: the namespace tree (nodes), versions, blobs (the record of bytes, ref-counted), shares, identity, the change journal, and the transactional outbox.

Object storage holds bytes only; an object with no committed Postgres row does not exist and is reclaimed by GC. The commit protocol (06 §4) writes the version, the blob refcount, and the outbox event in one transaction.

Postgres features we rely on: ACID transactions, foreign keys, RLS (ADR-0007), jsonb (metadata/outbox payloads), partial indexes (outbox drainer), and full-text search for v1 (ADR-0009).

Consequences

Positive

Negative / costs

Alternatives considered