Skip to content

SyMqtt design decisions

SyMqtt was built with a core directive: Predictability and safety over magic features.

In industrial IoT and mission-critical distributed systems, hidden framework behaviors are dangerous. We intentionally excluded several seemingly attractive features to guarantee deterministic behavior and protect your hardware infrastructure.


1. No hidden auto-retries (order over “magic”)

Section titled “1. No hidden auto-retries (order over “magic”)”
  • The temptation: Automatically retrying a failed Request-Response call under the hood.
  • The danger: In industrial automation, command ordering is critical. If a Stop_Motor command times out due to a transient network glitch, and the framework silently retries it while the application has already issued a subsequent Start_Motor_New_Speed command, the operations can execute out of order at the broker level. This causes severe, hard-to-debug race conditions.
  • Our decision: SyMqtt reports failures instantly via timeouts. Resiliency strategies (retries, exponential backoffs, circuit breakers) must be explicitly managed by your business logic, where command sequence context is fully understood.

2. Post-connection immutability (safety over mutations)

Section titled “2. Post-connection immutability (safety over mutations)”
  • The temptation: Allowing users to dynamically inject, mutate, or delete channels and topics on SyMqttBox while the client is actively connected.
  • The danger: Runtime mutations introduce complex thread locking, memory overhead, and unpredictable state synchronization bugs across high-load background workers.
  • Our decision: Topology configuration is strictly declarative during startup. If your infrastructure changes radically at runtime, the safe path is a controlled disconnection, re-configuration, and a clean re-connection. Predictable state is safe state.

3. Delimiter-based text envelopes (no heavy dependencies)

Section titled “3. Delimiter-based text envelopes (no heavy dependencies)”
  • The temptation: Embedding complex JSON, Protobuf, or MessagePack serializers inside the transport envelope parsing phase.
  • The danger: Microcontrollers (Arduino, ESP32) frequently lack the memory or CPU power to process heavy objects natively, while backend microservices have wildly varying serialization standards.
  • Our decision: The SerialMessage convention uses a high-speed, lightweight text delimiter scheme ([Id],[Contents]). The Contents property is a raw string. If your system requires JSON or binary payloads, your application layer handles that execution in a single line of code, keeping the core transport engine dependencies at absolute zero.

4. Timeout-driven lifecycle (trusting the broker)

Section titled “4. Timeout-driven lifecycle (trusting the broker)”
  • The temptation: Purging all pending synchronous requests from the internal queue the exact millisecond a network disconnect event is intercepted.
  • The danger: MQTT brokers often handle brief reconnections gracefully. If a connection drops for 500ms and restores itself immediately, a response might still arrive safely before the application’s timeout expires. Kill-on-disconnect would unnecessarily break “in-flight” requests that could have succeeded.
  • Our decision: Time is the ultimate judge. Pending requests live or die strictly based on their configured Timeout.