Skip to main content

ADR-0003: One SQLite database behind role-specific store interfaces

Status: Accepted · 2026-07-14

Decision

The vertical slice uses a single SQLite database file (WAL mode) as the physical store, but code accesses it only through logical role interfaces mirroring the reference architecture’s polyglot model: Every row carries a non-null tenant_id; repository helpers refuse queries without tenant scope.

Context

Local development and tests must be credential-free (product invariant). SQLite via bun:sqlite is synchronous, fast, transactional, and supports FTS5 and recursive CTEs — enough to implement real semantics (durable jobs, projections, bounded traversals) rather than in-memory fakes. What matters for the slice is that the contracts are the polyglot ones, so store substitution is additive.

Consequences

  • Projections (search/graph) are rebuildable from the system of record via explicit rebuild jobs and carry watermarks — enforced by the interfaces, not convention.
  • Single-writer SQLite limits concurrency; acceptable at slice scale. The capacity model (docs/capacity-model.md) covers when each role must move out.
  • Graph queries are bounded (depth/edge-type/limit parameters are mandatory).