Handling Large JSON Files (>50MB) in Browser and Node.js
An engineering guide to overcoming V8 string buffer limits, implementing streaming AST tokenizers, and avoiding memory leaks.
1. The V8 Memory Multiplier Effect
A common developer misconception is that a 10MB JSON file consumes 10MB of RAM. In reality, JavaScript engines (such as V8 in Chrome and Node.js) represent JSON strings in UTF-16 internally (2 bytes per character).
When JSON.parse() is invoked:
- The raw file string is loaded into memory (~20MB RAM for a 10MB disk file).
- The parser allocates JavaScript object wrappers, shape descriptors (Hidden Classes), and hash tables for keys.
- The resulting in-memory object graph frequently requires 4x to 8x the raw payload size.
2. Streaming Architecture in Node.js with stream-json
To process a 2GB database export without exceeding Node.js memory boundaries (JavaScript heap out of memory), use a streaming token pipeline:
import fs from "fs";
import { parser } from "stream-json";
import { streamArray } from "stream-json/streamers/StreamArray.js";
const pipeline = fs.createReadStream("massive-dataset.json")
.pipe(parser())
.pipe(streamArray());
let recordCount = 0;
pipeline.on("data", ({ key, value }) => {
recordCount++;
// Process each individual object in O(1) memory
if (recordCount % 10000 === 0) {
console.log(`Processed ${recordCount} records.`);
}
});
pipeline.on("end", () => {
console.log(`Completed parsing ${recordCount} items with stable memory.`);
}); 3. Web Worker Offloading in the Browser
FormJson isolates heavy AST manipulation inside independent Web Workers. By utilizing postMessage() with Transferable Objects (ArrayBuffers), raw payloads transfer between threads with zero CPU copy overhead, ensuring the browser UI never drops a single frame.