ADR 0010: Deployment — containers, expand/migrate/contract, Kubernetes optional
Status: Accepted
Date: 2026-07-19
Context
First production release should be one well-structured deployment, not a Kubernetes prerequisite.
Decision
- Deployable units:
web,admin,control,api,workercontainers + PostgreSQL, Redis, object storage, OTel collector.adminmay deploy withwebinitially but stays a separate app boundary;controlhas stricter network/auth policy.
- Migrations follow expand → backfill → contract; zero-downtime compatible; migration locks prevent concurrent runs.
- Environment is validated at process start by
@vercia/config; processes refuse to boot on invalid config.
- Health/readiness endpoints + graceful shutdown with queue drain in the worker.
- Kubernetes is an optional profile (
infra/k8s), never required for local dev or first release.
Consequences
- One VM + Compose can run the whole platform; horizontal scaling is adding API/worker replicas.
Single-image runtime update (2026-10-11)
The supported single image runs the API, compiled worker, and four Next surfaces under supervisor. Nginx selects web/admin/control/docs by distinct public hostnames so each application keeps its root URLs and assets. The configuration renderer validates origins and ports; /api/v1 goes to Nest while application API routes remain with their Next app. Internal server requests use a private API URL. API readiness checks the database with a timeout. Production migrations use a separate owner before the restricted runtime processes start.
The pnpm 9 monorepo dependency graph is retained in the image; unsupported recursive pruning is not used. .dockerignore excludes local environment secrets, installed dependencies, and generated artifacts from the build context.
Explicit hosted staging and shared PostgreSQL (2026-10-11)
The owner authorized a hosted merchant staging environment with email, paid
platform subscriptions and realtime calls deferred. NODE_ENV remains production.
Only the explicit staging profile permits disabled adapters; they fail with
standard precondition errors, report unavailable capabilities and never report
successful transmission, payments or room grants. Memory email and fake billing
remain forbidden in production; fake realtime media is now forbidden there too.
Commercial production configuration remains the default and requires the real
email/billing providers. Merchant-owned commerce payment accounts remain separate.
For an existing PostgreSQL server, administrators provision a dedicated database,
restricted migration owner and runtime role before release. The migration job can
validate preprovisioned credentials without creating roles or rotating passwords.
Only the dedicated database/schema is migrated; the runtime role cannot own tables,
assume another role, bypass RLS or modify the migration ledger. Hosting reuse does
not authorize changing another application's data, credentials or configuration.