Gateway heartbeat
Every gateway maintains a persistent WebSocket to the cloud and sends a heartbeat message on a fixed cadence. The cloud marks a gateway offline when the heartbeat stops arriving.
Cadence and timeouts
Source of truth: gateway/internal/cloud/client.go (gateway side) and cloud/internal/devices/gateway_ws.go (cloud side).
| Parameter | Value | Configurable via | Notes |
|---|---|---|---|
| Heartbeat interval (gateway -> cloud) | 30 s | heartbeat_interval_sec in gateway config | Cadence at which the gateway sends a heartbeat WebSocket message. |
| WebSocket ping interval (cloud -> gateway) | 30 s | PingInterval in GatewayWSHubConfig | Keep-alive ping from the cloud. |
| WebSocket pong timeout | 10 s | PongTimeout in GatewayWSHubConfig | If no pong within 10 s after a ping, the cloud tears down the connection. |
| Write timeout | 10 s | WriteTimeout | Timeout for a single WebSocket write on either side. |
| Offline threshold | 90 s | gwOfflineTimeout (cloud) | If the cloud sees no heartbeat for 90 s, the gateway status transitions to offline. |
| Offline check interval | 15 s | gwOfflineCheckInt (cloud) | How often the cloud sweeps connected gateways for expired heartbeats. |
| Command timeout | 30 s | gwCommandTimeout | Cloud-to-gateway commands fail if no response arrives in 30 s. |
| Reconnect backoff (max) | operator-configured | reconnect_max_backoff_sec in gateway config | Cap on exponential backoff after a disconnect. |
Heartbeat payload fields
Sent by the gateway to the cloud as {"type":"heartbeat","data":<HeartbeatData>} on the interval above.
| Field | Type | Description |
|---|---|---|
cpu_percent | float | CPU utilisation sampled at heartbeat time. |
memory_mb | integer | Resident memory in MB. |
version | string | Gateway binary version. |
timestamp | ISO-8601 timestamp | Time the heartbeat was sampled (UTC). |
camera_recording_status | object | Map of camera_id -> state for cameras currently recording. Omitted when empty. |
network_throughput | object | Bytes in/out delta since the previous heartbeat. Omitted when unavailable. |
B-10 (audit 2026-05-23):
cameras_onlineandcameras_totalwere removed from the payload — the cloud never parsed them. The fleet camera-online count surfaced in the dashboard is computed from thecameras.statusDB column directly. The cloud parser still tolerates the legacy fields in inbound bodies so older gateway binaries can roll forward without a coordinated cut-over.
Network throughput sub-object
| Field | Type | Description |
|---|---|---|
bytes_in | uint64 | Bytes received on the primary interface since the last heartbeat. |
bytes_out | uint64 | Bytes transmitted on the primary interface since the last heartbeat. |
measured_at | ISO-8601 timestamp | Time the throughput sample ended. |
Status transitions
| From | To | Trigger |
|---|---|---|
online | offline | No heartbeat received for 90 s. |
offline | online | Any heartbeat or WebSocket reconnect. |
offline or online | disabled | Admin disables the gateway (not automatic). |
disabled | online | Admin re-enables and a heartbeat arrives. |
Related
- Ports and protocols — WebSocket endpoint and firewall rules
- Gateway shows offline — fix path when the heartbeat stops
- Install a gateway — initial pairing and first heartbeat