ADR-0002: Service Structure
Status
Section titled “Status”Accepted and amended on 2026-08-04.
Context
Section titled “Context”Creating empty deployables before their contracts exist adds build, deployment, secret, monitoring, and operational cost without product capability.
Decision
Section titled “Decision”The current platform contains:
web-console;platform-api;- documentation;
- PostgreSQL/TimescaleDB and its migration Job.
mqtt-ingestion-workeras the independently connected, singleton Netmore MQTT receiver;raw-storage-workeras the independently scalable JetStream consumer;- NATS JetStream as the bounded durable handoff between those workers.
Shared configuration, contracts, persistence, logging, operability, and flow engine capabilities remain packages.
The final names of the first two ingestion deployables are
mqtt-ingestion-worker and raw-storage-worker. ADR-0009 later introduced
flow-worker, script-sandbox-worker, and flow-action-worker as concrete,
separately scalable and isolated capabilities.
The durable broker is introduced with the first real consumer, not kept running as speculative infrastructure.
Consequences
Section titled “Consequences”The repository contains no empty worker skeletons. Each future deployable must justify independent scaling, connection lifecycle, retry boundary, security isolation, or operational ownership and must arrive with tests, configuration, Helm values, metrics, and documentation.
The two workers are justified by different connection and durability boundaries: the receiver controls MQTT PUBACK backpressure and never accesses PostgreSQL, while the storage worker can scale against one durable pull consumer and owns the database transaction.