Configurable WebSocket Transport Parameters and Rate Limits in TREK

TREK exposes five tunable WebSocket settings—including payload size, origin filtering, and per-connection message throttling—through environment variables and compile-time constants in server/src/websocket.ts.

TREK’s real-time communication layer is built on the ws library, with transport behavior and security constraints centralized in a single module. Understanding these configurable WebSocket transport parameters and rate limits allows operators to harden deployments against abuse or scale throughput for high-traffic scenarios.


WebSocket Transport Parameters

The setupWebSocket function in server/src/websocket.ts initializes the server with a concise set of transport options that govern how connections are established and maintained.

Connection Path and Payload Size

By default, the server mounts the WebSocket endpoint at /ws and caps individual message size at 64 KB. These values are passed directly to the underlying ws constructor.

  • path: Fixed at /ws (line 40).
  • maxPayload: Set to 64 * 1024 bytes (line 41).

To change the payload limit, edit the maxPayload option in setupWebSocket:

// server/src/websocket.ts
const wss = new WebSocketServer({
  path: '/ws',
  maxPayload: 128 * 1024, // Increase to 128 KB
  // ... other options
});

Origin Validation

TREK supports strict origin whitelisting via the ALLOWED_ORIGINS environment variable. When this variable is set to a comma-separated list of origins, the server validates the Origin header against the list inside the verifyClient callback (lines 33–46).

If the header does not match an allowed entry, the handshake is rejected before the connection upgrades.


# .env

ALLOWED_ORIGINS=https://app.trek.io,https://admin.trek.io

When ALLOWED_ORIGINS is omitted, the server accepts connections from any origin.

Heartbeat Keep-Alive

To detect stale connections, the server emits an automatic ping every 30 seconds. The interval is controlled by the hard-coded constant HEARTBEAT_INTERVAL defined near line 49.

// server/src/websocket.ts (near line 49)
const HEARTBEAT_INTERVAL = 30000; // milliseconds

There is no runtime toggle for this value; it requires a source modification and redeployment.


Rate Limiting and Per-Connection Throttling

TREK implements a sliding-window rate limiter to prevent individual sockets from flooding the broadcast layer. The logic resides inside the message event handler and references two constants declared at the top of server/src/websocket.ts:

  • WS_MSG_LIMIT: Maximum messages allowed within the window (default 30).
  • WS_MSG_WINDOW: Time window in milliseconds (default 10,000).

When a client exceeds 30 messages in a 10-second window, the server emits an error payload to that specific socket and silently discards further inbound messages until the window slides forward.

These thresholds are suited for standard trip-update traffic but can be adjusted for high-frequency telemetry:

// server/src/websocket.ts (lines 27-28)
const WS_MSG_LIMIT = 100;    // Allow 100 messages
const WS_MSG_WINDOW = 5000;  // Per 5 seconds

Practical Configuration Examples

Restricting Origins via Environment Variable

Deploy the server with a strict origin policy to prevent unauthorized browser clients from connecting:

export ALLOWED_ORIGINS=https://trek.example.com
npm start

Tuning Rate Limits for High-Traffic Deployments

For fleet-tracking scenarios that emit frequent GPS updates, increase the constants in the source:

// server/src/websocket.ts
const WS_MSG_LIMIT = 200;
const WS_MSG_WINDOW = 10000;

Client Connection Handling

Clients receive a welcome payload containing their assigned socket ID upon successful connection:

const ws = new WebSocket('wss://api.trek.app/ws?token=' + jwtToken);

ws.addEventListener('message', (event) => {
  const payload = JSON.parse(event.data);
  if (payload.type === 'welcome') {
    console.log('Connected with socket ID:', payload.socketId);
  }
});

Broadcasting with Room Isolation

Server-side code can emit events to all participants in a specific trip room while excluding the originating socket to prevent echo:

import { broadcast } from './websocket';

broadcast(tripId, 'tripUpdated', { updatedAt: Date.now() }, originatingSocketId);

Summary

  • Path and payload: The endpoint is fixed at /ws with a 64 KB default payload cap, adjustable in setupWebSocket.
  • Origin control: Set ALLOWED_ORIGINS to a comma-separated list to enforce CORS-style validation during the handshake.
  • Heartbeat: A 30-second ping interval keeps connections alive; change HEARTBEAT_INTERVAL in the source if needed.
  • Rate limiting: The defaults of 30 messages per 10 seconds (configured via WS_MSG_LIMIT and WS_MSG_WINDOW) throttle abusive clients without affecting normal usage.
  • Implementation location: All parameters live in server/src/websocket.ts, making the real-time layer transparent and auditable.

Frequently Asked Questions

How do I restrict which domains can connect to the TREK WebSocket server?

Set the ALLOWED_ORIGINS environment variable to a comma-separated list of permitted origins before starting the server. The verifyClient logic inside setupWebSocket (lines 33–46) compares the incoming Origin header against this list and aborts the handshake if no match is found.

What happens when a client exceeds the rate limit?

When a socket sends more than WS_MSG_LIMIT messages within WS_MSG_WINDOW milliseconds, the server transmits an error payload to that client and stops processing further messages from the socket until the time window resets. Other connections in the same room remain unaffected.

Can I change the heartbeat interval without rebuilding the application?

No. The HEARTBEAT_INTERVAL constant (default 30 seconds) is hard-coded at line 49 of server/src/websocket.ts. Adjusting the keep-alive frequency requires editing the constant and recompiling or restarting the server.

Where are the WebSocket rate limit constants defined?

The per-connection rate limits are defined as constants at the top of server/src/websocket.ts: WS_MSG_LIMIT (default 30) on line 27 and WS_MSG_WINDOW (default 10000 ms) on line 28. These values are consumed by the message handler to enforce the sliding-window throttle.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →