Preparing search index...

    Connection Backpressure

    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:

    1. Instead of queuing more data (which would consume server memory), the server keeps only the latest value for each path
    2. When the client catches up, accumulated values are sent in a single delta with a $backpressure indicator
    3. Normal operation resumes automatically

    When 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.

    • Values are correct - the delta contains the latest values, only intermediate updates were dropped
    • Per-connection - backpressure is specific to each connection, not server-wide
    • Automatic recovery - the server exits backpressure mode as soon as the client catches up
    • Consider reducing scope - if backpressure is frequent, consider using granular subscriptions to reduce data volume
    1. Show a non-blocking warning - inform users without interrupting their workflow
    2. Auto-dismiss - clear the warning after a timeout (10 seconds is reasonable)
    3. Don't panic - backpressure is graceful degradation, not an error
    4. Log for debugging - record backpressure events to help diagnose network issues

    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)