SDK Transport Layer
The Tetrapus SDK transport stack handles QUIC connectivity, TLS, message batching, compression, priority routing, adaptive bandwidth, spill-to-disk buffering, and heartbeating. All behaviour is controlled through NerveConfig.
NerveConfig
Single entry-point for all client tuning. Serialisable as JSON, YAML, or TOML.
yaml NerveConfig auto-generated
| Field | Type | Default | Description |
|---|---|---|---|
| endpoint | String | "127.0.0.1:4433" | Server endpoint in `host:port` format (e.g., `"127.0.0.1:4433"`). Must be a valid [`SocketAddr`](std::net::SocketAddr) parseable string. The SDK connects over QUIC (UDP), so ensure the port is not firewalled for UDP traffic. |
| queue_capacity | usize | 10_000 | Maximum messages to buffer in the in-memory channel before backpressure engages. When the channel is full, new messages spill to the [`SpillBuffer`](crate::buffer::SpillBuffer) on disk rather than blocking the caller. Default: **10 000**. |
| batch_size | usize | 1400 | Maximum batch size in bytes. The [`MessageBatcher`](crate::transport::MessageBatcher) accumulates frames until this threshold is reached or `flush_interval_ms` expires, whichever comes first. Default: **1 400** (fits within a standard 1 500-byte Ethernet MTU after UDP/IP/QUIC headers). |
| flush_interval_ms | u64 | 10 | Maximum time (in milliseconds) to wait before flushing an incomplete batch. Lower values reduce latency at the cost of smaller (less efficient) batches. A value of **10** yields a 100 Hz flush cadence. Default: **10** ms. |
| connect_timeout_ms | u64 | 5000 | QUIC handshake timeout in milliseconds. If the server does not complete the TLS 1.3 handshake within this window, [`NerveClient::connect`](crate::NerveClient::connect) returns [`TransportError::HandshakeTimeout`](crate::error::TransportError::HandshakeTimeout). Default: **5 000** ms (5 seconds). |
| tls | TlsConfig | — | TLS configuration. See [`TlsConfig`] for details on certificate paths and the insecure mode toggle. |
| backoff_base_ms | u64 | 100 | Base delay in milliseconds for exponential backoff on reconnect. After a connection failure the SDK waits `backoff_base_ms` before the first retry, then doubles each subsequent attempt up to `backoff_max_ms`. Default: **100** ms. |
| backoff_max_ms | u64 | 30_000 | Maximum delay in milliseconds for exponential backoff. Caps the retry interval so the SDK does not wait indefinitely between reconnection attempts. Default: **30 000** ms (30 seconds). |
| circuit_breaker_threshold | u32 | 5 | Number of consecutive connection failures before the circuit breaker trips to the **Open** state. While open, all incoming messages are spilled to disk and no connection attempts are made until the backoff timer expires. Default: **5**. |
| heartbeat_interval_ms | u64 | 5000 | Heartbeat interval in milliseconds. A value of **0** disables heartbeats. When enabled, a dedicated QUIC stream sends periodic [`HeartbeatFrame`](crate::transport::HeartbeatFrame)s carrying queue depth, spill depth, and circuit breaker state so the server can detect device death by absence. Default: **5 000** ms (5 seconds). |
| compression | CompressionAlgo | — | Compression algorithm applied to each outgoing batch. Requires the corresponding feature flag (`compress-lz4` or `compress-zstd`) to be enabled; otherwise the batch is sent uncompressed with a 1-byte `0x00` prefix. Default: [`CompressionAlgo::None`](crate::transport::CompressionAlgo::None). |
Workload Tuning Guide
| Workload | queue_capacity | batch_size | flush_interval_ms | compression |
|---|---|---|---|---|
| IoT sensors 10 Hz | 1,000 | 1,400 | 100 | None |
| Fleet GPS 100 Hz | 10,000 | 1,400 | 10 | None |
| F1 telemetry 1 kHz | 50,000 | 4,096 | 5 | Lz4 |
| HFT tick data 5 kHz | 100,000 | 8,192 | 1 | Lz4 |
TLS Configuration
yaml TlsConfig auto-generated
| Field | Type | Default | Description |
|---|---|---|---|
| insecure | bool | false | Skip certificate verification. **WARNING:** Setting this to `true` in production is a security vulnerability. Use only for local development against self-signed certificates. |
| ca_cert_path | String | — | Path to a PEM-encoded CA certificate file. When set, only certificates signed by this CA are accepted. When `None`, the system trust store is used. |
| client_cert_path | String | — | Path to a PEM-encoded client certificate file (for mutual TLS). Both `client_cert_path` and `client_key_path` must be set for mTLS to activate. |
| client_key_path | String | — | Path to a PEM-encoded client private key file (for mutual TLS). Must correspond to the certificate in `client_cert_path`. |
Compression
Each batch is prefixed with a 1-byte wire ID identifying the compression algorithm.
enum CompressionAlgo auto-generated
| Variant | Fields | Description |
|---|---|---|
| None | — | No compression. Batch bytes are sent as-is with a `0x00` prefix. |
| Lz4 | — | LZ4 frame compression. Very fast (< 1 us per batch at typical sizes), moderate compression ratio (~2:1 on JSON telemetry). Recommended for high-throughput, latency-sensitive workloads. Requires feature flag: `compress-lz4`. |
Priority Routing
enum Priority auto-generated
| Variant | Fields | Description |
|---|---|---|
| Critical | — | Bypass batching, send immediately on the dedicated critical stream. Use for alerts, alarms, and safety-critical events that must reach the server with minimal latency. Each critical message is framed and compressed individually, so throughput is lower than batched priorities. |
| Normal | — | Standard batching behavior (default). Messages are accumulated in the [`MessageBatcher`](crate::transport::MessageBatcher) until the batch is full or the flush timer fires, then sent on one of the round-robin data streams. |
| Low | — | Larger batch threshold (4x), lower urgency. Messages are held longer in the batcher to produce larger, more efficient batches. Suitable for bulk data, periodic reports, or any telemetry that does not require sub-second delivery. |
Spill Buffer
When the in-memory queue fills or the QUIC connection is down, messages spill to a file-backed ring buffer. On reconnect, spilled messages drain before the live queue to preserve ordering.
yaml SpillPolicy auto-generated
| Field | Type | Default | Description |
|---|---|---|---|
| max_disk_bytes | u64 | 64 * 1024 * 1024 | Maximum size of the spill file in bytes. When the file exceeds this limit, the `EvictionStrategy` is applied. Default: **67 108 864** (64 MiB). |
| max_age_secs | u64 | 3600 | Maximum age of spilled messages in seconds. Messages older than this are eligible for eviction regardless of disk usage. Default: **3 600** (1 hour). |
| eviction | EvictionStrategy | — | Strategy applied when the spill file reaches `max_disk_bytes`. Default: `OldestFirst`. |
| spill_path | String | /tmp/nerve-sdk-spill.bin | File system path for the spill file. The directory must exist and be writable. The file is created lazily on the first spill. Default: `"/tmp/nerve-sdk-spill.bin"`. |
Adaptive Bandwidth
The BandwidthEstimator classifies link quality from RTT samples and adjusts batching parameters automatically.
enum LinkTier auto-generated
| Variant | Fields | Description |
|---|---|---|
| HighBandwidth | — | Low latency, high throughput (average RTT < 50 ms). Uses default MTU-sized batches with no compression overhead. Typical for LAN and co-located deployments. |
| Constrained | — | Moderate latency (50 -- 200 ms average RTT). Increases batch size to 4 KiB, extends flush interval to 50 ms, and enables compression. Typical for cellular (4G/5G) or cross-region links. |
| Degraded | — | High latency or packet loss (average RTT > 200 ms). Maximises batch size to 8 KiB, extends flush interval to 200 ms, and forces compression. Typical for satellite links or severely degraded networks. |
Heartbeat Protocol
A dedicated QUIC stream sends fixed 19-byte heartbeat frames at the configured interval. The server uses these to detect client health and queue pressure.
Wire format (magic: 0xBEAF LE):
[magic: u16 = 0xBEAF LE][ts_ns: u64 LE][queue_depth: u32 LE][spill_depth: u32 LE][circuit_state: u8] Circuit state: 0 = Closed (healthy), 1 = Open (tripped), 2 = HalfOpen (probing).
Questions?
Reach out for help with integration, deployment, or custom domain codecs.