heap memory use increasing with langgraph invocations on node server #371

Open
opened 2026-02-15 18:16:18 -05:00 by yindo · 2 comments
Owner

Originally created by @orangewit3 on GitHub (Oct 21, 2025).

Checked other resources

  • I added a very descriptive title to this issue.
  • I searched the LangGraph.js documentation with the integrated search.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangGraph.js rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package).

Example Code

N/A

Error Message and Stack Trace (if applicable)

No response

Description

langgraph invocations are leaking heap between requests (Node + LangGraph/LangChain)

TL;DR: After two back-to-back langgraph invocations on a warm server, heap never returns to baseline. Biggest deltas: strings +~2.3 MB (duplicate prompts/config blobs) and compiled code +~3.5 MB (per-request instruction streams/functions). Under load this pushes Render into OOM/restarts.

What I did

Instrumented the server with heap snapshots: capture before request, run langgraph, capture after, repeat for a second request, then run a comparison.

Image Image Image

What I’m seeing

I've attached a couple screenshots showing the heap comparison between consecutive requests showing the heap increases for the string and compiled code sections.

Strings ballooning (~+2.3 MB / 2 reqs). They’re our long prompt bodies (repeated prompts) and generation config JSON.
Ref: “Filter by class → string” shows many repeats of the same long prompt text.

“Compiled code” ballooning (~+3.5 MB / 2 reqs).
Retainers point to instruction streams (_prepareSingleTask, _parse, _Request, ClientRequest, pipelineImpl) chained to ChatGoogleGenerativeAI in @langchain/google-genai/dist/chat_models.cjs.
Ref: compiled code delta + retainers tree.

Smaller persistent growths (5–10 KB each/request). Objects from setContextVariable('UserDetails') and setContextVariable('CartDetails') stick around. I suspect artifacts and a few other run objects too (needs a focused snapshot to confirm).

Node does not GC at end of HTTP request. Anything still strongly referenced (module cache, closure, event listener, etc.) persists.

Why it matters

Heap climbs with every http request → steady climb to OOM → Render kills/restarts. That’s exactly what we’re seeing under moderate burst.

Likely causes (most → least)

Prompt/template duplication + retention.
We pull from Prompt Hub each request and build fresh ChatPromptTemplates. Those carry large strings and appear to remain referenced. I tried a quick Map cache keyed by prompt name; growth still happens → either the cache pins instances, or other references exist (templates copied into new graph instances each run, captured by closures, etc.).

Graph/model plumbing rebuilt per run and retained.
“Compiled code” growth + retainers tied to ChatGoogleGenerativeAI implies new functions/instruction streams (parsers, validators, pipeline steps) per invocation, and something holds references so they never get collected.

Request context + artifacts leaking scope.
setContextVariable(...) values and possibly artifacts aren’t purely ephemeral; they’re likely ending up in long-lived structures or listeners.

Repro (minimal)

Start Node server (LangGraph; Prompt Hub; LangChain @langchain/google-genai).

Warm with first request.

Take Heap A.

Send two identical http requests.

Take Heap B and compare.

Observe strings and compiled code heap sections increasing, retained via prompt strings and instruction streams linked to ChatGoogleGenerativeAI.

Environment

Node on Render.

LangGraph/LangSmith orchestration.

Prompt Hub fetch.

LangChain @langchain/google-genai client.

Default Node flags (no --expose-gc in prod).

What I tried

Naive Map cache for prompts → no change. Either cache pins or there are additional references beyond the cache (graph copies, closures, listeners).

What this likely means

Strong references exist past request end (module caches, event listeners, run registries, client singletons done wrong, etc.).

If LangGraph/LangSmith deep-copies graph elements (templates, tools, validators) per run and keeps a reference (esp. with tracing), that would explain the compiled-code growth. So hoping someone can provide more clarity on this issue and propose a strategy for fixing this!

System Info

Node version: v22.13.1
Operating system: darwin arm64
Package manager: npm
Package manager version: N/A

zod -> @3.24.3, , @"^3.22.4", @"^3.23.8", @"^3.24.1"
@langchain/anthropic -> @0.3.19, , @"^0.3.19", @""
@langchain/core -> @0.3.57, , @"^0.3.50", @">=0.3.48, @">=0.3.55, @">=0.2.36, @">=0.2.31, @">=0.2.21
langsmith -> @0.3.29, , @"^0.3.29"
@langchain/google-genai -> @0.2.10, , @"^0.2.7", @"
"
@langchain/langgraph -> @0.2.67, , @"^0.2.67"
@langchain/langgraph-checkpoint -> @0.0.17, , @"~0.0.17"
@langchain/langgraph-sdk -> @0.0.74, , @"~0.0.32"
@langchain/openai -> @0.5.8, , @"^0.5.8", @">=0.1.0
langchain -> @0.3.27, , @"^0.3.27"

Originally created by @orangewit3 on GitHub (Oct 21, 2025). ### Checked other resources - [x] I added a very descriptive title to this issue. - [x] I searched the LangGraph.js documentation with the integrated search. - [x] I used the GitHub search to find a similar question and didn't find it. - [x] I am sure that this is a bug in LangGraph.js rather than my code. - [x] The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package). ### Example Code N/A ### Error Message and Stack Trace (if applicable) _No response_ ### Description **langgraph invocations are leaking heap between requests (Node + LangGraph/LangChain)** TL;DR: After two back-to-back langgraph invocations on a warm server, heap never returns to baseline. Biggest deltas: strings +~2.3 MB (duplicate prompts/config blobs) and compiled code +~3.5 MB (per-request instruction streams/functions). Under load this pushes Render into OOM/restarts. **What I did** Instrumented the server with heap snapshots: capture before request, run langgraph, capture after, repeat for a second request, then run a comparison. <img width="1329" height="582" alt="Image" src="https://github.com/user-attachments/assets/5df5221f-c67c-43f9-96fe-8bd8996ee05d" /> <img width="1339" height="389" alt="Image" src="https://github.com/user-attachments/assets/6566bfe4-e392-4578-af4a-de73b73ed105" /> <img width="1341" height="404" alt="Image" src="https://github.com/user-attachments/assets/b3ef6fc6-41c8-4b0f-b258-1ab00a9e8456" /> **What I’m seeing** I've attached a couple screenshots showing the heap comparison between consecutive requests showing the heap increases for the string and compiled code sections. Strings ballooning (~+2.3 MB / 2 reqs). They’re our long prompt bodies (repeated prompts) and generation config JSON. Ref: “Filter by class → string” shows many repeats of the same long prompt text. “Compiled code” ballooning (~+3.5 MB / 2 reqs). Retainers point to instruction streams (_prepareSingleTask, _parse, _Request, ClientRequest, pipelineImpl) chained to ChatGoogleGenerativeAI in @langchain/google-genai/dist/chat_models.cjs. Ref: compiled code delta + retainers tree. Smaller persistent growths (5–10 KB each/request). Objects from setContextVariable('UserDetails') and setContextVariable('CartDetails') stick around. I suspect artifacts and a few other run objects too (needs a focused snapshot to confirm). Node does not GC at end of HTTP request. Anything still strongly referenced (module cache, closure, event listener, etc.) persists. **Why it matters** Heap climbs with every http request → steady climb to OOM → Render kills/restarts. That’s exactly what we’re seeing under moderate burst. Likely causes (most → least) Prompt/template duplication + retention. We pull from Prompt Hub each request and build fresh ChatPromptTemplates. Those carry large strings and appear to remain referenced. I tried a quick Map cache keyed by prompt name; growth still happens → either the cache pins instances, or other references exist (templates copied into new graph instances each run, captured by closures, etc.). Graph/model plumbing rebuilt per run and retained. “Compiled code” growth + retainers tied to ChatGoogleGenerativeAI implies new functions/instruction streams (parsers, validators, pipeline steps) per invocation, and something holds references so they never get collected. Request context + artifacts leaking scope. setContextVariable(...) values and possibly artifacts aren’t purely ephemeral; they’re likely ending up in long-lived structures or listeners. **Repro (minimal)** Start Node server (LangGraph; Prompt Hub; LangChain @langchain/google-genai). Warm with first request. Take Heap A. Send two identical http requests. Take Heap B and compare. Observe strings and compiled code heap sections increasing, retained via prompt strings and instruction streams linked to ChatGoogleGenerativeAI. **Environment** Node on Render. LangGraph/LangSmith orchestration. Prompt Hub fetch. LangChain @langchain/google-genai client. Default Node flags (no --expose-gc in prod). **What I tried** Naive Map cache for prompts → no change. Either cache pins or there are additional references beyond the cache (graph copies, closures, listeners). **What this likely means** Strong references exist past request end (module caches, event listeners, run registries, client singletons done wrong, etc.). If LangGraph/LangSmith deep-copies graph elements (templates, tools, validators) per run and keeps a reference (esp. with tracing), that would explain the compiled-code growth. So hoping someone can provide more clarity on this issue and propose a strategy for fixing this! ### System Info Node version: v22.13.1 Operating system: darwin arm64 Package manager: npm Package manager version: N/A -------------------- zod -> @3.24.3, , @"^3.22.4", @"^3.23.8", @"^3.24.1" @langchain/anthropic -> @0.3.19, , @"^0.3.19", @"*" @langchain/core -> @0.3.57, , @"^0.3.50", @">=0.3.48, @">=0.3.55, @">=0.2.36, @">=0.2.31, @">=0.2.21 langsmith -> @0.3.29, , @"^0.3.29" @langchain/google-genai -> @0.2.10, , @"^0.2.7", @"*" @langchain/langgraph -> @0.2.67, , @"^0.2.67" @langchain/langgraph-checkpoint -> @0.0.17, , @"~0.0.17" @langchain/langgraph-sdk -> @0.0.74, , @"~0.0.32" @langchain/openai -> @0.5.8, , @"^0.5.8", @">=0.1.0 langchain -> @0.3.27, , @"^0.3.27"
Author
Owner

@jakartasipirok commented on GitHub (Oct 23, 2025):

experiencing the same issue

@jakartasipirok commented on GitHub (Oct 23, 2025): experiencing the same issue
Author
Owner

@jasontjahjono commented on GitHub (Oct 26, 2025):

I'm also experiencing the exact same issue! Please help fix this

Image
@jasontjahjono commented on GitHub (Oct 26, 2025): I'm also experiencing the exact same issue! Please help fix this <img width="975" height="409" alt="Image" src="https://github.com/user-attachments/assets/0eb88bce-9728-40a4-a4a5-8590ad4becc8" />
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraphjs#371