The problem
Shore operators must verify fire-related conditions on hundreds of fishing vessels that each send live video and sensor telemetry over intermittent links.
System architecture
flowchart LR
subgraph edge ["Vessel edge"]
edge_0(["Onboard sensors and encoders"])
edge_1["Video encode for HLS"]
end
subgraph shore ["Shore ingest"]
shore_0["Thin telemetry ingest"]
shore_1["HLS origin for operators"]
shore_2[["Safety event queue"]]
shore_3[["Routine telemetry queue"]]
end
subgraph consume ["Operator view"]
consume_0[("Alarm and event store")]
consume_1["Pre-aggregated dashboard reads"]
consume_2["HLS player for verification"]
end
edge_0 --> shore_0
edge_0 --> edge_1
shore_0 -->|"priority events"| shore_2
shore_0 --> shore_3
shore_2 --> consume_0
shore_3 --> consume_1
edge_1 --> shore_1
shore_1 --> consume_2Key architecture decisions
Dedicated queue for safety events
Safety-class messages use a separate RabbitMQ path with their own consumer capacity.
After an outage, routine data piles up; alarms still need to surface in seconds.
Rejected Single queue with consumer priority only — rejected because one slow message can still hold up the messages queued behind it.
Trade-off Two paths to scale, monitor, and tune independently.
HLS for live view, not for event latency
Operators verify visually over HLS; fire-related events travel on the telemetry event path.
HLS latency is bounded by segment duration and playlist depth; it is the wrong SLA for a safety event.
Rejected Using video analytics latency as the operational alarm SLA.
Trade-off Operators accept a few seconds of glass-to-glass delay on video while events stay on the fast path.
Dashboards read aggregates, not ingest tables
Heavy reporting queries hit pre-aggregated or roll-up tables, not live ingest servers.
A dashboard scan during a spike must not slow ingest, including safety events.
Rejected Querying raw ingest from the API request path.
Trade-off Maintaining read models as data arrives; brief staleness on charts is acceptable.
What I own, wrote, and delegate
Own
- Shore-side Node.js backend architecture for ingest and operator APIs
- Separation of safety events from routine telemetry
Wrote
- Concurrent ingestion and event pipeline for fleet-wide telemetry
- HLS live path integration for operator verification
Delegate
- Onboard firmware and actuation hardware outside the shore backend scope
Scale
- Several hundred fishing vessels, each with video and telemetry streams
- HLS live view ~3s in-region, ~5s when viewed cross-region (operator path, not alert latency)
- Safety events include abnormal temperature, smoke, electrical spark, and open flame
Boundaries
- The product name includes automatic firefighting. The work here is shore-side monitoring and the event backend.
- Actuation and the automatic response on the vessel sit on the ship, outside this shore backend.
What we watch in operation
Rules the design never breaks
- Routine processing stalls do not block safety events.
- One organisation cannot read another organisation's vessels.
- Cross-region video delay is explained as network and playlist buffering, not mixed with event SLA.
Broader application
- Remote fleets on intermittent cellular or satellite links.
- Control rooms that must see live video before dispatching a response.
- Platforms that separate safety-critical events from routine telemetry.