Przejdź do treści

ADR 004 — SaaS first, single-tenant deployable

Status: Accepted Date: 2026-05-09

Context

Compliance buyers in defence, financial services, and central government often ask whether the platform can be deployed inside their own environment — a single-tenant, customer-controlled deployment, sometimes called sovereign deployment or on-premise.

The trade-off is well-known. Multi-tenant SaaS is operationally cheap (one set of running services, one upgrade path, one observability stack) but politically harder to sell to security-conscious buyers. Per-customer deployment is operationally expensive but easier to sell to those same buyers.

We need to choose a default while leaving the door open.

Decision

Multi-tenant SaaS is the default. Single-tenant deployable is the escape hatch for customers that contractually require it.

The codebase enforces this with a small number of constraints:

  • All shared infrastructure assumptions are gated through environment variables: database URL, Redis URL, blob storage backend, secret management backend. There is no hard-coded "Secruna SaaS" assumption anywhere in cp-api or discovery-worker.
  • The Postgres RLS policies (see Operating principles) were designed for multi-tenant but degenerate cleanly to single-tenant — one tenant row, one path, every query passes.
  • The discovery-worker Container Apps Job is replaceable by any arq-compatible worker process. A customer running their own Kubernetes can swap the Container Apps deployment for a Job/CronJob manifest without code changes.

We do not support single-tenant deployment as a self-serve product today — a single-tenant deployment is a contractual engagement with Secruna engineering, not a "download the Helm chart" experience. That will come (Plan 87 WI-4 — pluggable extractors, production OSS hosting) but only when a customer pays for it.

Consequences

Positive

  • A single product, a single codebase, a single upgrade path. Every customer benefits from every fix to every other customer.
  • The SaaS deployment economics work at any customer count above zero — there is no infrastructure floor we have to amortise across customers.
  • When a sovereign-deployment customer signs, the codebase is ready; we do not have to refactor environment assumptions out of the hot path.

Negative

  • Some prospects walk because they need single-tenant today and we are not selling it self-serve. Those conversations are recoverable through engagement contracts, but the cycle is long.
  • The constraint of "deployment-portable through env vars" rules out some otherwise-attractive cloud-native shortcuts (e.g. baking Azure-specific identity flows into the API). We keep paying that tax to preserve the option.