ADR-0012 — Tiered packaging: Compose (self-host) + Helm (K8s/SaaS)
- Status: Accepted
- Date: 2026-06-11
- Related: 01 §3 Ledger, 03 NFR-8, 06 §8, ADR-0001
V1 Freeze (2026-06-12): Accepted (tiered). lite and standard tiers (Docker Compose) are V1. The full tier (OpenSearch + extracted workers) and Helm/K8s SaaS packaging are deferred to P3/P4.
Context
BitVault must be self-hostable (developer/small team, minimal ops) and SaaS-capable on Kubernetes — from one codebase (G6). These pull in opposite directions: self-host wants few moving parts; SaaS wants horizontal scale and the full async plane. The brief’s six stateful dependencies would be an adoption killer for self-host (Ledger). Three “deployment models” (self-host, SaaS, multi-tenant) must not become three codebases.
Decision
One artifact, two packagings, three dependency tiers.
- Same image(s), config-profiled.
bitvaultdruns all modules in v1 (ADR-0001); a config profile selects which dependencies/features are active. No build-time forks between self-host and SaaS. - Dependency tiers:
- lite —
bitvaultd+ PostgreSQL + object store (MinIO). In-process event bus; Postgres-FTS search. The “it just runs” self-host default. - standard — lite + Redis (cache/sessions/rate-limit) + NATS (externalized bus).
- full — standard + OpenSearch (content search) + separate worker deployments. The SaaS configuration.
- lite —
- Packagings:
- Docker Compose files per tier for self-host (
compose/docker-compose.{lite, standard,full}.yml). - Helm chart with
values.{lite,standard,full}.yamlfor K8s/SaaS — statelessDeployments + HPA + PDB + NetworkPolicies; stateful deps via operators (CloudNativePG, etc.) or managed cloud services (toggle in values).
- Docker Compose files per tier for self-host (
- Multi-tenancy is a runtime mode, not a packaging (ADR-0007) — the same binary serves one tenant (self-host) or many (SaaS).
- Images: multi-stage, minimal (distroless/scratch), non-root, healthchecked.
Consequences
Positive
- Self-host can be two dependencies (
lite) — competitive with Nextcloud’s footprint; directly addresses the adoption-killer risk (Ledger). - One codebase serves all deployment models (G6); no fork drift.
- Tiers map exactly to the evolution phases (09) and to which features are enabled.
- K8s-first story (HPA/PDB/NetworkPolicy/operators) is intact for the portfolio.
Negative / costs
- Features must degrade gracefully by tier (e.g. content search absent in lite) — requires capability checks and honest UI (real work, enforced by tests per tier).
- A test matrix across tiers (CI must run at least lite + full e2e).
- Helm values surface area is large; mitigated by sane defaults per profile.
Alternatives considered
- Separate self-host vs SaaS codebases/builds: rejected — guaranteed drift; violates G6.
- Kubernetes-only (no Compose): rejected — too heavy a barrier for self-host
adoption; Compose
liteis the on-ramp. - Bundle everything always (no tiers): rejected — forces six stateful deps on every self-hoster (the Ledger’s adoption killer).