Analyzing Node.js .heapsnapshot Files and Using heapquery for Memory‑Leak Investigation

The article shows how to generate a Node.js V8 heap snapshot with v8.getHeapSnapshot, explains the JSON‑like .heapsnapshot structure of nodes, edges, and strings, and demonstrates using the heapquery tool to import the data into SQLite for SQL queries that locate and trace memory‑leaking objects such as a HugeObj instance.

NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
Analyzing Node.js .heapsnapshot Files and Using heapquery for Memory‑Leak Investigation

This article explains how to obtain a heap snapshot in Node.js via v8.getHeapSnapshot, examines the internal .heapsnapshot file format, and demonstrates how to leverage the heapquery tool to query heap data with SQL.

Using v8.getHeapSnapshot

In Node you can call v8.getHeapSnapshot to generate a .heapsnapshot file that contains a snapshot of the current V8 heap. The following example creates a large object and writes a snapshot:

const { writeHeapSnapshot } = require("v8");
class HugeObj {
  constructor() {
    this.hugeData = Buffer.alloc((1 << 20) * 50, 0);
  }
}
module.exports.data = new HugeObj();
writeHeapSnapshot();

Running the script with node test.js produces a file such as Heap.20210228.154141.9320.0.001.heapsnapshot, which can be opened in Chrome DevTools.

Structure of a .heapsnapshot File

The file is JSON‑like. The top‑level snapshot object contains meta‑information, while the heavy data lives in three arrays: nodes, edges and strings. nodes and edges are stored as flat integer sequences, each line representing one node or edge.

Each node is serialized by HeapSnapshotJSONSerializer::SerializeNode and consists of the fields (type, name, id, self_size, edge_count, trace_node_id). The order of the fields is defined in snapshot.meta.node_fields, and the corresponding types are listed in snapshot.meta.node_types. Values are stored as numbers; strings are stored as indices into the strings array.

Example of a node line (formatted for readability):

{
  "nodes": [9,1,1,0,10,0, // first node
            9,2,3,0,23,0  // second node
  ]
}

The edge array follows a similar scheme. Each edge stores (type, edge_name_or_index, to). The type and name/index are resolved using snapshot.meta.edge_fields and snapshot.meta.edge_types.

Node‑Edge Relationship

During snapshot generation V8 builds a graph where each node knows the number of outgoing edges ( edge_count). The method HeapSnapshot::FillChildren reorganises edges so that the first edge_count entries belong to the first node, the next edge_count entries belong to the second node, and so on. This allows the file to be traversed without storing explicit "from" references.

Querying the Snapshot with heapquery

heapquery

is a tiny utility (available in JavaScript and Rust) that parses a .heapsnapshot file and imports the data into a SQLite database. After running: npx heapquery path_to_your_heapdump.heapsnapshot you obtain path_to_your_heapdump.db. You can then explore the heap with ordinary SQL, for example: SELECT * FROM node ORDER BY self_size DESC; and trace ownership chains:

SELECT from_node, B.name AS from_node_name
FROM edge AS A
JOIN node AS B ON A.from_node = B.id
WHERE A.to_node = 51389;

The article walks through a concrete investigation of a memory leak caused by a HugeObj instance, showing how to locate the leaking object, follow its incoming edges, and finally discover the constructor definition in the source code.

Conclusion

By understanding the .heapsnapshot format and the V8 internals that produce it, developers can go beyond the visual Chrome DevTools UI and perform custom analyses with SQL. The heapquery tool demonstrates one practical way to turn raw heap data into actionable insights for backend Node.js applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

SQLNode.jsmemory leakV8heapqueryHeapSnapshot
NetEase Cloud Music Tech Team
Written by

NetEase Cloud Music Tech Team

Official account of NetEase Cloud Music Tech Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.