1. Minimizing Message Size
| Technique | Saving |
| Short keys | Replace "timestamp" with "t" |
| Binary format | MessagePack/Protobuf vs JSON |
| Delta vs full | Patches, not snapshots |
| Omit defaults | Skip null/zero fields |
| Dictionary IDs | Send enum int instead of string |
2. Batching Messages
| Trigger | Latency Impact |
| 10-20ms window | Imperceptible |
| N messages | Bounded throughput |
| Byte threshold | Network-efficient |
Note: Batching converts many small frames into one larger frame, amortizing TLS/framing overhead.
| Format | Size (vs JSON) |
| MessagePack | 50-70% |
| CBOR | 50-70% |
| Protobuf | 20-40% |
| FlatBuffers | 20-40% (zero-copy) |
| Custom TLV | Smallest possible |
4. Implementing Message Throttling
Example: requestAnimationFrame throttle
let pending = null;
function throttleSend(cursor) {
pending = cursor;
if (throttleSend.scheduled) return;
throttleSend.scheduled = true;
requestAnimationFrame(() => {
ws.send(JSON.stringify({ "type":"cursor", "pos": pending }));
throttleSend.scheduled = false;
});
}
| Approach | Use |
| throttle (leading) | Fixed-rate updates |
| debounce (trailing) | Quiet-after typing |
| rAF | UI sync (cursor, scroll) |
5. Optimizing JSON Parsing
| Technique | Detail |
| Avoid double parse | Parse once, share parsed |
| Lazy fields | Defer heavy decode |
| simdjson (Node) | SIMD-accelerated parser |
| Pre-validate length | Reject oversized before parse |
6. Reusing Buffers
Example: Buffer pool
const pool = [];
function get(size) { return pool.pop() ?? new Uint8Array(size); }
function release(buf) { if (pool.length < 64) pool.push(buf); }
| Strategy | Use |
| Pool by size | Avoid alloc churn |
| Reset (zero) on release | Security if reused across users |
| Bounded pool | Prevent memory hoarding |
7. Reducing Event Listener Overhead
| Anti-pattern | Fix |
| Many handlers per WS | Single router |
| Closures per handler | Hoist + bind |
| Re-create on reconnect | Reuse via AbortController |
8. Implementing Lazy Parsing
| Technique | Detail |
| Parse envelope only | Defer payload until needed |
| Type-based dispatch | Skip if no handler |
| Streaming JSON | For very large messages |
| Tool | Insight |
| Chrome Performance | Main-thread cost |
clinic.js flame | Node CPU hot spots |
0x | Flamegraphs |
perf / dtrace | System-level |
10. Load Testing Connections
| Tool | Use |
| k6 (xk6-websocket) | Scriptable, modern |
| Artillery | YAML scenarios, WS plugin |
| Tsung | Distributed load |
| autocannon-ws (custom) | Quick benchmarks |