Deployment Model
Current Core
Section titled “Current Core”The portable chart and approved environment contracts deploy:
web-consolein test and as the pending Production rollout target;platform-api;- the documentation application;
- PostgreSQL/TimescaleDB;
- a database migration Job.
- a single-replica NATS JetStream StatefulSet with a 4-GiB test/default PVC and a metrics-only Prometheus exporter sidecar;
- a versioned raw-stream bootstrap Job;
raw-storage-worker;- singleton
mqtt-ingestion-workerwithRecreatestrategy; - an hourly raw-retention CronJob.
The chart also contains flow-worker, script-sandbox-worker, and
flow-action-worker. They are disabled by default until the flow production
gates and environment-specific credentials are approved.
The production web console uses the approved
https://app.iot-sens.schlossers.at endpoint. Production activation remains a
manual Argo CD synchronization after automated GitOps contract validation.
There is no legacy decoder worker or mock MQTT broker. Test and production values render the raw-ingestion topology; external GitOps mappings and live activation still follow the staged rollout runbook.
Environments
Section titled “Environments”Test and production use the same product images and Helm chart with environment-specific values, Secrets, namespaces, persistent volumes, and Ingress configuration. Production promotion remains manual.
Current public hosts:
| Capability | Test | Production |
|---|---|---|
| Platform API | api.dev.iot-sens.schlossers.at | api.iot-sens.schlossers.at |
| Documentation | docs.dev.iot-sens.schlossers.at | docs.iot-sens.schlossers.at |
| Web console | test-frontend.dev.iot-sens.schlossers.at | app.iot-sens.schlossers.at (pending sync) |
No cloud provider, storage class, TLS issuer, DNS name, or registry is hard-coded in application code. Environment differences belong in Helm values, Secrets, and GitOps release selection.
Raw-ingestion topology
Section titled “Raw-ingestion topology”Netmore MQTT -> mqtt-ingestion-worker -> NATS JetStream -> raw-storage-worker -> TimescaleDBFlow execution extends the pipeline only after raw persistence:
Raw DB commit -> transactional outbox -> raw-stored stream -> flow-worker -> measurements -> action outbox -> flow-action-workerThe MQTT receiver does not dual-publish into parallel raw and flow queues.
Persistence
Section titled “Persistence”TimescaleDB uses environment-specific persistent volumes. Database migrations run before application workloads through Argo CD sync waves. Removing an application workload must never remove the TimescaleDB PVC.
NATS storage uses a 3.8-GB server file-store ceiling and its own PVC. Test and new default installations request 4 GiB; Production retains its existing 5-GiB claim. An existing 2-GiB test claim requires a controlled expansion or reprovisioning because a StatefulSet volume-claim template cannot be changed in place. The Raw Ingestion work queue has a 2-GiB limit; the smaller reference and control streams reserve 1 GiB for Raw Stored, 128 MiB for Actions, and 32 MiB each for Replay and Dead Letters. Their declared maxima total 3,422,552,064 bytes and fit below the server ceiling. Acknowledged Raw Ingestion messages are removed after their PostgreSQL commit. Raw Stored is also a work queue with a 1-GiB limit and 7-day maximum age; Flow acknowledgements remove committed references immediately. JetStream is not a database backup. Stream creation follows the database migration and precedes the raw consumer and MQTT receiver through Argo CD sync waves.
Changing an existing Raw Stored stream from limits retention to work-queue retention requires a maintenance window. Helm exposes a one-time guarded bootstrap mode and refuses to render it while MQTT ingestion, raw storage, or the Flow worker is enabled. The guard deletes only the known legacy stream after its consumer is fully drained and stable for five seconds.