Skip to content

ADR-0010: Embedded SQLite for the access-log store

Status: Accepted — 003-governance-depth (2026-07) Principles served: III, IV Source: specs/003-governance-depth/research.md G-3; specs/003-governance-depth/plan.md Complexity Tracking

Context

Per-app data-access records must remain queryable for the app's entire lifetime, which requires durable storage — but no platform database exists (001 is CR-only), and the log is a single-writer, append-only stream at internal-app volume (tens of apps, not thousands). Standing up an operated database for that would be the largest infrastructure addition of the feature for the smallest workload.

Decision

The data gateway embeds SQLite via modernc.org/sqlite — pure Go, no CGO, which keeps the distroless/static builds the services use — on a PersistentVolumeClaim, in WAL mode, with append-only writes indexed by app and timestamp. Retention is for the app's lifetime. The store is exposed ONLY through the gateway's query API (GET /v1/logs?app=, plus GET /v1/logs/summary); nothing else reads the file. That query API is deliberately the seam a real database slots into later.

Alternatives considered

  • bbolt — rejected: per-app/time-window queries and lifetime-retention bookkeeping are SQL-shaped.
  • A platform Postgres (e.g. CloudNativePG) — rejected: a single-writer log at tens-of-apps volume does not justify an operated database that no other feature needs yet; revisit when evidence-index scale or HA demands it.

Consequences

This is a recorded Complexity Tracking entry: an embedded store on a PVC instead of a platform database, chosen as the smallest honest footprint. Because access is exclusively via the gateway API, swapping in a real database later changes one service's internals, not any consumer. The log is telemetry behind an API, not authoritative state on the App CR, so Principle IV holds. Gateway readiness is tied to a writable store — "can't log → don't serve" — so a full or broken PVC fails closed rather than serving unlogged data. Single-writer embedded storage means no HA for the log path; that is the recorded trigger for revisiting.