--- name: node-style path: package.json description: Use when writing or reviewing code in a Node.js or TypeScript project. --- # Node Coding Style Rules distilled from TigerBeetle's TigerStyle, Node.js, and V8 internals. Current APIs, defaults, and numbers: [references/canonical.md](references/canonical.md). ## Goals Safety before performance before developer experience, in that order. Wrong but fast is worthless. ## Design first Sketch before code: network, disk, memory, CPU, each by bandwidth and latency. Attack the slowest resource first, weighted by how often it is used. Design-phase wins are 1000x. Post-profile wins are 10x. ## Rules - Put a limit on everything: loops, queues, batches, request sizes, input lengths. - Batch everything: IO, requests, parsing, allocation. Fixed costs pay for many items. - Bound work per tick. The event loop is the fairness scheduler, one callback is one small turn. - Never block the loop: no sync fs, crypto, zlib, child_process in servers. No giant JSON on the loop. No unproven regex on input. - Respect backpressure: `write() === false` means stop until `drain`. Compose streams with `pipeline()`. - Keep shapes stable: same properties, same order, every time. Never `delete`. Hot call sites stay monomorphic. - Bytes in Buffer or TypedArray: bulk data never rides through strings. Share memory instead of copying. - Allocation rate is the lever: when GC runs, your code does not. - Chunk or offload CPU work: yield per chunk on the loop, or use a bounded worker pool. Transfer buffers, never clone. - Validate at boundaries, handle every error path, fail fast. - Drain queues at your own pace: work per tick, not work per event. - Small functions: pure leaves, control flow centralized in one place. - Say why: comments carry rationale, not narration. ## Never - Unbounded anything, even temporarily. - O(n) work over attacker-sized input on the loop. - Performance work without an envelope sketch. - Trading correctness for latency.