Signal K Server includes automatic backpressure handling to gracefully manage slow client connections on WebSocket, Signal K TCP (port 8375), and NMEA TCP (port 10110) interfaces. This document explains how to detect and handle backpressure events in your webapp or plugin.
When a client connection can't keep up with the data rate, the server enters "backpressure mode" for that connection:
$backpressure indicatorWhen the server flushes accumulated values after a backpressure period, it adds a $backpressure property to the delta:
ws.onmessage = (event) => {
const msg = JSON.parse(event.data)
if (msg.$backpressure) {
// This delta contains accumulated values from a backpressure period
console.warn(
`Backpressure: ${msg.$backpressure.accumulated} paths accumulated over ${msg.$backpressure.duration}ms`
)
// Show a user notification
showNetworkWarning(
'Network congestion detected - some updates were skipped'
)
}
// Process delta normally - values are still valid (just the latest ones)
handleDelta(msg)
}
Normal delta:
{
"context": "vessels.urn:mrn:imo:mmsi:123456789",
"updates": [
{
"$source": "n2k-01.115",
"timestamp": "2024-01-15T10:30:00.000Z",
"values": [
{
"path": "navigation.position",
"value": { "latitude": 60.0, "longitude": 25.0 }
}
]
}
]
}
Backpressure flush delta:
{
"context": "vessels.urn:mrn:imo:mmsi:123456789",
"updates": [...],
"$backpressure": {
"accumulated": 42,
"duration": 1250
}
}
| Property | Type | Description |
|---|---|---|
$backpressure.accumulated |
number | Number of unique context:path:$source combinations that were accumulated |
$backpressure.duration |
number | Milliseconds the server was in backpressure mode for this client |
| Interface | Strategy | Details |
|---|---|---|
| WebSocket (Primus) | Accumulate + flush | Keeps latest value per path, flushes with $backpressure indicator when client catches up |
| Signal K TCP (port 8375) | Accumulate + flush | Same behavior as WebSocket for subscription deltas |
| NMEA TCP (port 10110) | Drop + disconnect | NMEA sentences are stateless; sentences are dropped for slow clients, connection terminated if buffer stays over hard limit |
| TCP client (outbound) | Drop | Outbound writes are skipped when the remote server's buffer is full |
WebSocket, Signal K TCP, and NMEA TCP connections share the configurable thresholds BACKPRESSURE_ENTER, MAXSENDBUFFERSIZE, and MAXSENDBUFFERCHECKTIME. The TCP client (outbound) uses only BACKPRESSURE_ENTER for write gating.
Environment variables for testing (not recommended for production):
# Lower thresholds for testing
BACKPRESSURE_ENTER=1024 # Enter backpressure at 1KB (default: 512KB)
BACKPRESSURE_EXIT=0 # Exit when buffer is empty (default: 1KB)