Buffers Best Practices
Buffers are the right tool for small, known-size binary work - for everything else, cap sizes, prefer streams, and treat encoding and secrets explicitly.
How to Use This List
- Apply to upload handlers, webhooks, TCP parsers, and crypto utilities.
- Any unchecked item is a blocker for paths accepting untrusted bytes.
- Pair with Streams Best Practices for large I/O.
- Security items are mandatory for auth and payment flows.
A - Size and Memory
- Stream files larger than a few MB instead of
readFileinto one Buffer. Constant memory under load. - Enforce
MAX_FRAMEor body size limits on binary parsers. Reject oversize length prefixes before allocation. - Pre-size
Buffer.concatwhen total length is known. Avoid O(n²) realloc on many chunks. - Avoid accumulating unbounded chunk arrays from sockets. Parse incrementally or use Transform streams.
- Monitor heap when handling uploads. Alert on growth correlated with traffic.
B - Allocation and Encoding
- Use
Buffer.allocfor secrets and crypto material. NotallocUnsafeunless immediately overwritten fully. - Specify
utf8explicitly intoString/fromfor text. Document legacy encodings in ADR if unavoidable. - Use
TextDecoderwithfatal: truefor inbound text protocols. Reject malformed sequences at boundary. - Normalize Unicode (NFC) before comparison of user identifiers. Prevents homograph bypass.
- Use
Buffer.byteLengthfor UTF-8 size limits. Not string.length.
C - Security
- Compare secrets with
crypto.timingSafeEqualon equal-length digests. No raw===on API keys. - Never echo buffer contents in errors or logs. Generic client messages; server-side correlation IDs.
- Wipe short-lived key buffers in
finallywhen feasible.buffer.fill(0)best-effort hygiene. - Parse HMAC/signatures on raw body Buffer before JSON parse. Preserve byte-exact payload for verify.
- Cap hex/base64 decode output size. Prevent decompression bombs.
D - Protocols and Interop
- Document endianness and frame layout in protocol spec. Big-endian unless stated otherwise.
- Handle partial TCP reads with an accumulator. Never assume
dataevent equals one message. - Version binary message types or use protobuf/msgpack schemas. Evolvable contracts.
- Prefer
subarrayoverslicefor zero-copy views. Copy when retaining beyond next read. - Use Web-standard
TextEncoder/Uint8Arrayat fetch boundaries. Interop with browser clients.
E - When Not to Use Buffers
- Do not represent domain objects as raw Buffers in business logic. Parse to typed structures at boundary.
- Do not use Buffers for numbers - use typed arrays or protobuf. Clear schema beats ad-hoc bytes.
- Do not stringify binary as
latin1for "preservation". Explicit hex/base64 with size limits instead. - Reach for streams when transforming large payloads. gzip, CSV parse, S3 upload pipelines.
- Reach for JSON when debuggability beats byte efficiency. Binary only with measured need.
FAQs
What is a safe max body buffer size?
Depends on API - typical REST 1-10 MB at reverse proxy and app. Stricter for auth endpoints.
When is allocUnsafe OK?
Internal pooling of non-sensitive chunks you fully write before any read - never user-facing secrets.
Should I use Buffer or Uint8Array?
Buffer extends Uint8Array - use either; prefer Web APIs at isomorphic boundaries.
How do buffers interact with worker_threads?
Transfer ArrayBuffers to avoid copy - document ownership transfer semantics.
Does JSON.parse need Buffer?
Decode UTF-8 to string first with fatal decoder - then parse - or limit size before decode.
What about multipart uploads?
Stream to disk or S3 - do not buffer entire file in RAM.
Are template literals on buffers safe?
No - ${buf} coerces to string and may leak content in logs.
How do I test frame parsers?
Split known frame across multiple feed() calls in node:test.
Should protobuf replace all binary?
Only where schema stability and throughput justify complexity - not for one-off scripts.
What links to stream guidance?
Streams Best Practices for pipeline and backpressure rules.
How does this relate to Fastify?
Set bodyLimit and use streams for large downloads - Fastify defaults are not unlimited safety.
Is base64 storage for secrets OK?
No at rest - use KMS/Vault. Base64 transport OK with TLS and short lifetime.
Related
- Buffers Basics - core APIs
- Buffer Security - timing-safe compare
- Streams Best Practices - large data paths
- Binary Protocols - framing patterns
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.